阅片及影像预览页更新

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"
},
"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",
"@riophae/vue-treeselect": "0.4.0",
"ali-oss": "^6.17.1",
@ -27,10 +20,10 @@
"babel-eslint": "7.2.3",
"copy-webpack-plugin": "^4.5.2",
"core-js": "^3.8.3",
"cornerstone-core": "^2.3.0",
"cornerstone-math": "^0.1.8",
"cornerstone-tools": "^6.0.8",
"cornerstone-wado-image-loader": "^3.1.2",
"cornerstone-core": "^2.6.1",
"cornerstone-math": "^0.1.10",
"cornerstone-tools": "^6.0.10",
"cornerstone-wado-image-loader": "^4.13.2",
"dcmjs": "^0.29.8",
"dicom-parser": "^1.8.9",
"dicomedit": "^0.1.0",
@ -44,7 +37,6 @@
"jszip": "^3.7.1",
"moment": "^2.27.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"streamsaver": "^2.0.6",
"node-sass": "^4.14.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",
@ -54,6 +46,7 @@
"sass-loader": "^8.0.0",
"screenfull": "^4.2.0",
"sortablejs": "^1.15.0",
"streamsaver": "^2.0.6",
"v-viewer": "^1.6.4",
"vcrontab": "^0.3.5",
"vue": "^2.6.11",

View File

@ -226,3 +226,17 @@ export function confirmTaskReminder(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;"
class="cornerstone-element"
@contextmenu.prevent="onContextmenu"
@mousemove="sliderMousemove"
@mouseup="sliderMouseup"
>
<div v-show="dicomInfo.series" class="info-series">
@ -54,7 +53,7 @@
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</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>
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
@ -82,16 +81,25 @@
<!-- <div v-show="stack.firstImageLoading" class="load-indicator">
Loading Series #{{ stack.seriesNumber }}...
</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>
</template>
<script>
import Vue from 'vue'
import Contextmenu from 'vue-contextmenujs'
Vue.use(Contextmenu)
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneMath from 'cornerstone-math'
import * as cornerstoneTools from 'cornerstone-tools'
const scroll = cornerstoneTools.import('util/scrollToIndex')
import Hammer from 'hammerjs'
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()
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
import DicomTags from './DicomTags'
export default {
name: 'DicomCanvas',
components: { DicomTags },
data() {
return {
loading: false,
@ -163,7 +173,10 @@ export default {
isMove: false
},
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', () => {
this.sliderMouseup()
})
document.addEventListener('mousemove', (e) => {
this.sliderMousemove(e)
})
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
},
@ -196,7 +212,7 @@ export default {
this.stack.seriesId = dicomSeries.seriesId
this.stack.seriesNumber = dicomSeries.seriesNumber
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.description = dicomSeries.description
this.toolState.viewportInvert = false
@ -205,15 +221,19 @@ export default {
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId
if (this.toolState.clipPlaying) this.toggleClipPlay()
this.toolState.clipPlaying = false
const element = this.$refs.canvas
cornerstone.enable(element)
cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false
this.loading = true
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(image => {
this.loading = false
this.onFirstImageLoaded(image)
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
this.onFirstImageLoaded(image)
}
}).catch((error) => {
this.loading = false
if (error.error && error.error.message) {
@ -242,7 +262,13 @@ export default {
apiTool
)
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
@ -302,7 +328,7 @@ export default {
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
cornerstoneTools.addToolState(this.canvas, 'stack', this.stack)
// cornerstoneTools.stackPrefetch.enable(this.canvas)
cornerstone.updateImage(element, true)
cornerstone.updateImage(element, true)
// cornerstoneTools.stackPrefetch.setConfiguration({ maxImagesToPrefetch: Infinity,
// preserveExistingPool: true })
// cornerstoneTools.stackPrefetch.enable(this.canvas)
@ -356,6 +382,12 @@ export default {
if (this.dicomInfo.thick) {
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) {
const { detail } = e
@ -403,6 +435,7 @@ export default {
this.dicomInfo.location = position
},
getOrientationMarker(element) {
console.log('getOrientationMarker')
const enabledElement = cornerstone.getEnabledElement(element)
const imagePlane = cornerstone.metaData.get(
'imagePlaneModule',
@ -426,6 +459,7 @@ export default {
if (!markers) {
return
}
this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
this.setMarkers()
@ -438,10 +472,10 @@ export default {
}
},
onImageLoaded(e) {
var image = e.detail.image
// var seriesIndex = -1
var seriesUid = image.data.string('x0020000e')
console.log(seriesUid)
// var image = e.detail.image
// // var seriesIndex = -1
// var seriesUid = image.data.string('x0020000e')
// console.log(seriesUid)
},
getToolForElement(toolName) {
var isExist = false
@ -521,6 +555,9 @@ export default {
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
this.sliderInfo.oldM = e.clientY
this.sliderInfo.isMove = true
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
},
sliderMousemove(e) {
if (!this.sliderInfo.isMove) return
@ -540,6 +577,13 @@ export default {
sliderMouseup(e) {
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() {
this.toolState.clipPlaying = false
},
@ -610,6 +654,7 @@ export default {
enabledElement.renderingTools.renderCanvasData = renderCanvasData
},
scrollPage(offset) {
if (this.loading) return
var index = this.stack.currentImageIdIndex + offset
if (index < 0) index = 0
else if (index >= this.stack.imageIds.length) {
@ -621,6 +666,7 @@ export default {
},
toggleClipPlay() {
if (this.loading) return
if (this.toolState.clipPlaying) {
cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false
@ -640,7 +686,7 @@ export default {
resetWwwc() {
this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = false
// viewport.invert = false
var image = cornerstone.getImage(this.canvas)
viewport.voi.windowWidth = image.windowWidth
viewport.voi.windowCenter = image.windowCenter
@ -675,8 +721,11 @@ export default {
},
resetRotate() {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
if (this.originalMarkers.length > 0) {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
var viewport = cornerstone.getViewport(this.canvas)
viewport.hflip = false
viewport.vflip = false
@ -685,24 +734,26 @@ export default {
},
setRotate(hflip, vflip, angle, type) {
var markers = [...this.orientationMarkers]
if (type === 2) {
//
this.orientationMarkers[1] = markers[3]
if (this.orientationMarkers.length > 0) {
var markers = [...this.orientationMarkers]
if (type === 2) {
//
this.orientationMarkers[1] = markers[3]
this.orientationMarkers[3] = markers[1]
} else if (type === 3) {
//
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 4) {
// 90
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 90
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
this.orientationMarkers[3] = markers[1]
} else if (type === 3) {
//
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 4) {
// 90
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 90
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
}
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas)
if (hflip) viewport.hflip = !viewport.hflip
if (vflip) viewport.vflip = !viewport.vflip
@ -714,6 +765,9 @@ export default {
var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
},
showTags() {
this.dcmTag.visible = true
},
fitToWindow() {
if (this.stack.seriesNumber) {
cornerstone.fitToWindow(this.canvas)
@ -840,194 +894,197 @@ export default {
synchronizer.remove(this.$refs.canvas)
this.setAllToolsPassive()
},
onContextmenu(event) {
const colormapsList = cornerstone.colors.getColormapsList()
const colorItems = []
colorItems.push({
label: '默认值',
onClick: () => {
this.setColormap()
}
})
colormapsList.forEach(colormap => {
const item = {}
item.label = colormap.name
item.onClick = () => {
this.setColormap(colormap.id)
}
colorItems.push(item)
})
this.$contextmenu({
items: [
{
label: '移动',
divided: true,
onClick: () => {
this.setToolActive('Pan')
}
},
{
label: '缩放',
divided: true,
children: [
{
label: '自由缩放',
onClick: () => {
this.setToolActive('Zoom')
}
},
{
label: '适应图像',
onClick: () => {
this.fitToWindow()
}
},
{
label: '适应窗口',
onClick: () => {
this.fitToImage()
}
}
]
},
{
label: '透镜',
divided: true,
onClick: () => {
this.setToolActive('Magnify')
}
},
{
label: '旋转',
divided: true,
children: [
{
label: '默认值',
onClick: () => {
this.resetRotate()
}
},
{
label: '自由旋转',
onClick: () => {
this.setToolActive('Rotate')
}
},
{
label: '水平翻转',
onClick: () => {
this.setRotate(true, false, 0)
}
},
{
label: '垂直翻转',
onClick: () => {
this.setRotate(false, true, 0)
}
},
{
label: '左转90度',
onClick: () => {
this.setRotate(false, false, -90)
}
},
{
label: '右转90度',
onClick: () => {
this.setRotate(false, false, 90)
}
}
]
},
onContextmenu(e) {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
// const colormapsList = cornerstone.colors.getColormapsList()
// const colorItems = []
// colorItems.push({
// label: '',
// onClick: () => {
// this.setColormap()
// }
// })
// colormapsList.forEach(colormap => {
// const item = {}
// item.label = colormap.name
// item.onClick = () => {
// this.setColormap(colormap.id)
// }
// colorItems.push(item)
// })
// this.$contextmenu({
// items: [
// {
// label: '',
// divided: true,
// onClick: () => {
// this.setToolActive('Pan')
// }
// },
// {
// label: '',
// divided: true,
// children: [
// {
// label: '',
// onClick: () => {
// this.setToolActive('Zoom')
// }
// },
// {
// label: '',
// onClick: () => {
// this.fitToWindow()
// }
// },
// {
// label: '',
// onClick: () => {
// this.fitToImage()
// }
// }
// ]
// },
// {
// label: '',
// divided: true,
// onClick: () => {
// this.setToolActive('Magnify')
// }
// },
// {
// label: '',
// divided: true,
// children: [
// {
// label: '',
// onClick: () => {
// this.resetRotate()
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('Rotate')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setRotate(true, false, 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: '测量',
divided: true,
minWidth: 0,
children: [
{
label: '探针',
onClick: () => {
this.setToolActive('Probe')
}
},
{
label: '长度测量',
onClick: () => {
this.setToolActive('Length')
}
},
{
label: '角度测量',
onClick: () => {
this.setToolActive('Angle')
}
},
{
label: 'Cobb测量',
onClick: () => {
this.setToolActive('CobbAngle')
}
},
{
label: '椭圆测量',
onClick: () => {
this.setToolActive('EllipticalRoi')
}
},
{
label: '矩形测量',
onClick: () => {
this.setToolActive('RectangleRoi')
}
},
{
label: '多边形标记',
onClick: () => {
this.setToolActive('FreehandRoi')
}
},
{
label: '十字线',
onClick: () => {
this.setToolActive('Bidirectional')
}
},
{
label: '文字标注',
onClick: () => {
this.setToolActive('ArrowAnnotate')
}
}
]
},
{
label: '调窗',
divided: true,
onClick: () => {
this.setToolActive('Wwwc')
}
},
{
label: '反色',
divided: true,
onClick: () => {
this.toggleInvert()
}
},
{
label: '伪彩',
children: colorItems
}
],
event,
// x: event.clientX,
// y: event.clientY,
customClass: 'class-a',
zIndex: 3,
minWidth: 100
})
return false
// {
// label: '',
// divided: true,
// minWidth: 0,
// children: [
// {
// label: '',
// onClick: () => {
// this.setToolActive('Probe')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('Length')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('Angle')
// }
// },
// {
// label: 'Cobb',
// onClick: () => {
// this.setToolActive('CobbAngle')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('EllipticalRoi')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('RectangleRoi')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('FreehandRoi')
// }
// },
// {
// label: '线',
// onClick: () => {
// this.setToolActive('Bidirectional')
// }
// },
// {
// label: '',
// onClick: () => {
// this.setToolActive('ArrowAnnotate')
// }
// }
// ]
// },
// {
// label: '',
// divided: true,
// onClick: () => {
// this.setToolActive('Wwwc')
// }
// },
// {
// label: '',
// divided: true,
// onClick: () => {
// this.toggleInvert()
// }
// },
// {
// label: '',
// children: colorItems
// }
// ],
// event,
// // x: event.clientX,
// // y: event.clientY,
// customClass: 'class-a',
// zIndex: 3,
// minWidth: 100
// })
// return false
},
getToolSate() {
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')">
<svg-icon icon-class="zoom" style="font-size:20px;" />
</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')">
<svg-icon icon-class="fitToWindow" style="font-size:20px;" />
</button>
@ -169,19 +182,7 @@
<svg-icon icon-class="fitToImage" style="font-size:20px;" />
</button>
<!-- <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>
<!-- 测量标注 -->
@ -232,6 +233,10 @@
<button :title="$t('trials:dicom-show:image')" class="btn-link" @click="currentDicomCanvas.saveImage()">
<svg-icon icon-class="image" style="font-size:20px;" />
</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 class="measureTool-wrapper">
@ -247,7 +252,7 @@
<svg-icon icon-class="previousframe" style="font-size:20px;" />
</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
:icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'"
style="font-size:20px;"
@ -261,9 +266,10 @@
<button class="btn-link" :title="$t('trials:dicom-show:lastframe')" @click="currentDicomCanvas.scrollPage(9999)">
<svg-icon icon-class="lastframe" style="font-size:20px;" />
</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="20">20</option>
<option :value="30">30</option>
@ -386,7 +392,8 @@ export default {
wwwcList: [],
layout: null,
seriesList: [],
customWwc: { visible: false, title: null }
customWwc: { visible: false, title: null },
fps: 15
}
},
mounted() {
@ -400,8 +407,10 @@ export default {
methods: {
loadImageStack(dicomSeries) {
this.currentDicomCanvas.toolState.clipPlaying = false
this.$nextTick(() => {
this.currentDicomCanvas.loadImageStack(dicomSeries)
const series = Object.assign({}, dicomSeries)
this.currentDicomCanvas.loadImageStack(series)
})
},
loadOtherImageStack(seriesList) {
@ -411,7 +420,8 @@ export default {
Array.from(elements).forEach((element, index) => {
const canvasIndex = element.getAttribute('data-index')
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) {
this.currentDicomCanvas.setFps(event.target.value)
},
clipPlay() {
this.currentDicomCanvas.setFps(this.fps)
this.currentDicomCanvas.toggleClipPlay()
},
fitToType(e, type) {
const toolButtons = document.querySelectorAll('[data-tool]')
Array.from(toolButtons).forEach((toolBtn) => {
@ -879,13 +893,19 @@ export default {
background-color: #323232;
min-width: 80px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
border: 1px solid #4e4e4e;
padding: 5px;
}
.dicom-wrapper .dropdown:hover .dropdown-content {
display: block;
}
.dicom-wrapper .dropdown-content p{
.dicom-wrapper .dropdown-content div{
height: 25px;
line-height: 25px;
cursor:point;
}
.dicom-wrapper .dropdown-content div:hover{
background-color: #16477b90;
}
</style>

File diff suppressed because it is too large Load Diff

View File

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

View File

@ -30,30 +30,55 @@ const getDefaultState = () => {
activeSeries: {},
lastCanvasTaskId: '',
imageQuality: null,
imageQualityIssues: null
imageQualityIssues: null,
currentLoadIns: []
}
}
function getQuestions(questions) {
const criterionType = parseInt(localStorage.getItem('CriterionType'))
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 => {
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'
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) {
var idx = item.TableQuestions.Questions.findIndex(i => i.QuestionMark === 11)
if (idx > -1) {
if (criterionType === 10) {
// pcwg
var lesionNum = getQuestionAnswer(item.TableQuestions.Questions, 11, answerObj)
answerObj.lesionNum = lesionNum
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 {
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
}
} else {
@ -69,7 +94,7 @@ function getQuestions(questions) {
}
function findQuestionAndRemoveLesion(questions, obj) {
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))
if (idx > -1) {
questions[i].TableQuestions.Answers.splice(idx, 1)
@ -85,7 +110,7 @@ function findQuestionAndRemoveLesion(questions, obj) {
function findQuestionAndUpdateLesion(questions, obj) {
for (var i = 0; i < questions.length; 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)
item.TableQuestions.Answers[idx].isLymphLesion = obj.isLymphLesion
item.TableQuestions.Answers[idx].loctation = obj.lesionOrgan
@ -114,10 +139,10 @@ function findQuestionAndUpdateLesion(questions, obj) {
}
function findQuestionAndAddLesion(questions, obj) {
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 = {}
questions[i].TableQuestions.Questions.forEach(item => {
sourceObj[item.Id] = ''
sourceObj[item.Id] = null
})
var targetObj = Object.assign(sourceObj, obj.lesionObj)
targetObj.IsCurrentTaskAdd = 'True'
@ -139,6 +164,22 @@ function getQuestionAnswer(questions, questionMark, answers) {
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
@ -190,6 +231,7 @@ const actions = {
},
getMasterSeries({ state }, obj) {
return new Promise(resolve => {
console.log('getMasterSeries')
var seriesInfo = {}
var i = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
getReadingVisitStudyList(obj.trialId, obj.visitId, obj.visitTaskId).then(res => {
@ -209,14 +251,28 @@ const actions = {
var seriesList = []
study.SeriesList.forEach((series, index) => {
const imageIds = []
series.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
const instanceList = []
// series.InstancePathList.forEach((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({
isDicom: study.IsDicom,
imageIds: imageIds,
instanceList: series.InstanceList,
instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
seriesId: series.Id,
imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid,
@ -481,24 +537,28 @@ const actions = {
return new Promise(async resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
var measureData = state.visitTaskList[index].MeasureData
console.log('removeCustomizeMeasuredData', obj, state.visitTaskList[index].MeasureData)
// var uuid = obj.measureData.data.uuid
// var idx = measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
console.log(obj, measureData)
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
console.log('idx', idx)
if (idx > -1) {
if (measureData[idx].FristAddTaskId) {
measureData[idx].MeasureData = ''
console.log('清除标记成功', idx)
} else {
measureData.splice(idx, 1)
console.log('移除标记成功', idx)
// console.log(obj, measureData)
if (obj.questionInfo.Id) {
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
console.log('idx', idx)
if (idx > -1) {
if (measureData[idx].FristAddTaskId) {
measureData[idx].MeasureData = ''
console.log('清除标记成功', idx)
} else {
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) {
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 (measureData[i].FristAddTaskId) {
measureData[i].MeasureData = ''
@ -508,7 +568,9 @@ const actions = {
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
}
// 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 measureData = state.visitTaskList[index].MeasureData
console.log('addOrUpdateNonTargetMeasuredData')
// item.MeasureData.data.remark === obj.orderMarkName
var idx = measureData.findIndex(item => item.QuestionId === obj.data.QuestionId && item.OrderMarkName === obj.data.OrderMarkName)
if (idx > -1) {
for (const k in state.visitTaskList[index].MeasureData[idx]) {
@ -632,29 +695,39 @@ const actions = {
var measureData = state.visitTaskList[index].MeasureData
console.log(measureData, obj)
// var idx = measureData.findIndex(item => item.MeasureData.uuid === obj.data.MeasureData.data.uuid)
if (!obj.questionInfo) {
state.visitTaskList[index].MeasureData.push({
MeasureData: obj,
SeriesId: obj.seriesId,
StudyId: obj.studyId,
InstanceId: obj.instanceId,
Id: obj.Id
})
console.log('新增标记成功')
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
// if (!obj.questionInfo) {
// state.visitTaskList[index].MeasureData.push({
// MeasureData: obj,
// SeriesId: obj.seriesId,
// StudyId: obj.studyId,
// InstanceId: obj.instanceId,
// Id: obj.Id
// })
// console.log('新增标记成功')
// resolve()
// }
var idx = measureData.findIndex(item => item.MeasureData.data.remark === obj.measureData.data.remark)
if (idx > -1) {
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].InstanceId = obj.instanceId
state.visitTaskList[index].MeasureData[idx].MeasureData = obj.measureData
// 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
console.log('更新标记成功', idx)
} 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('新增标记成功')
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
@ -720,15 +793,24 @@ const actions = {
})
},
getStudyInfo({ state }, obj) {
console.log('getStudyInfo')
return new Promise(resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
if (state.visitTaskList[index].studyListInit) {
resolve()
} else {
var studyList = []
// getVisitStudyList
// getReadingVisitStudyList
var keyImages = []
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) => {
const data = {}
data.StudyId = study.StudyId
@ -743,19 +825,47 @@ const actions = {
var seriesList = []
study.SeriesList.forEach((series, seriesIndex) => {
const imageIds = []
try {
// if (~window.location.href.indexOf('3c210000-3e2c-0016-4247-08dabf28e96b')) {
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}`)
})
} catch (e) {
console.log(e)
}
const instanceList = []
// try {
// series.InstancePathList.forEach((path) => {
// imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
// })
// } catch (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({
isDicom: study.IsDicom,
imageIds: imageIds,
instanceList: series.InstanceList,
instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
seriesId: series.Id,
imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid,
@ -782,7 +892,8 @@ const actions = {
isLoading: false,
isBeMark: series.IsBeMark,
ww: series.WindowWidth,
wc: series.WindowCenter
wc: series.WindowCenter,
isExistMutiFrames: series.IsExistMutiFrames
})
})
data.SeriesList = seriesList
@ -790,6 +901,7 @@ const actions = {
})
state.visitTaskList[index].StudyList = studyList
state.visitTaskList[index].studyListInit = true
state.visitTaskList[index].KeyImages = keyImages
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
@ -848,6 +960,115 @@ const actions = {
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) {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
state.visitTaskList[index].IsInit = true
@ -861,7 +1082,15 @@ const actions = {
},
setLastCanvasTaskId({ state }, taskId) {
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()
})
},

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()">
<span style="font-size:14px;color:#d0d0d0;margin:5px 0px;line-height: 25px;">返回列表</span>
</div> -->
<div class="studyDesc" style="line-height: 10px;">
<div class="studyDesc">
{{ studyTitle }}
</div>
<div class="studyDesc" style="line-height: 10px">
<div class="studyDesc">
{{ seriesCount }} Series
</div>
<div class="viewerSidethumbs ps" style="position: relative;">
@ -38,11 +38,12 @@
</span>
</span>-->
<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
v-show="item.instanceCount"
style="padding: 1px;"
>{{ item.instanceCount }} image
>{{ item.modality }} : {{ item.instanceCount }} image
</div>
</div>
</div>
@ -63,20 +64,24 @@
import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core'
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 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.cornerstone = cornerstone
// cornerstoneWADOImageLoader.webWorkerManager.initialize({
// webWorkerPath: './webWorker.js',
// taskConfiguration: {
// decodeTask: {
// codecsPath: './dicomCodecs.js'
// }
// }
// })
export default {
components: {
dicomViewer,
@ -86,6 +91,11 @@ export default {
uid: {
type: String,
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 wrapper = this.$refs['preview-wrapper']
wrapper.style.height = (totalHeight - 70) + 'px'
if (!dicomStore.studyList || !this.uid) return
if (!this.studyList || !this.uid) return
this.loadStudy()
},
@ -120,15 +130,14 @@ export default {
return newObj
},
loadStudy() {
var studyList = dicomStore.studyList
var studyList = this.studyList
var studyUid = this.uid
var studyItem = studyList.find(function(item) {
return item.dicomInfo.studyUid === studyUid
})
if (!studyItem) return
this.studyTitle =
studyItem.dicomInfo.patientName || studyItem.dicomInfo.description
this.studyTitle = studyItem.dicomInfo.description
this.seriesCount = studyItem.seriesList.length
var scope = this
@ -151,7 +160,8 @@ export default {
scope.seriesList.push({
seriesNumber: series.seriesNumber,
seriesTitle: series.description || series.modality || '(Anonymous)',
description: series.description,
modality: series.modality,
instanceCount: series.instanceList.length,
imageIds: imageIds,
previewImageId: imageIds[0]
@ -253,7 +263,7 @@ export default {
text-align: center;
background: rgb(88 84 83);
color: #d0d0d0;
padding: 2px;
padding: 5px;
}
.ps {

View File

@ -128,7 +128,7 @@ export default {
// imageIds.push(`wadouri:/api/instance/content/${item}`)
// })
// 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) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)

View File

@ -43,45 +43,73 @@
fit="fill"
>
<div class="viewernavitextwrapper">
<div v-if="item.keySeries" style="padding: 1px;color:red">
Key Images
</div>
<div v-else style="padding: 1px;">
#{{ item.seriesNumber }}
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div v-if="item.keySeries" style="color:red">
Key Images
</div>
<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 v-show="item.instanceCount" style="padding: 1px;">
{{ item.modality }}: {{ item.instanceCount }} image
</div>
<div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;">
T: {{ item.sliceThickness }}
T: {{ parseFloat(item.sliceThickness).toFixed(2) }}
</div>
<div v-show="!item.keySeries &&item.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
{{ item.description }}
</div>
<div v-if="!item.keySeries" style="padding: 1px;">
{{ item.prefetchInstanceCount }}/{{ item.instanceCount }}
{{ item.imageloadedArr.length }}/{{ item.instanceCount }}
</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>
<el-switch
v-model="item.isReading"
size="mini"
@change="changeReadingStatus($event, item)"
/>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="item.isDeleted"
size="mini"
@change="changeDeleteStatus($event, item)"
/>
<div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="item.isReading"
size="mini"
@change="changeReadingStatus($event, item)"
/>
</div>
<div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="item.isDeleted"
size="mini"
@change="changeDeleteStatus($event, item)"
/>
</div>
</div>
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount">
<el-progress :percentage="parseInt(((item.prefetchInstanceCount/item.instanceCount)*100).toFixed(2))" />
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount * 100">
<el-progress :percentage="parseInt((item.prefetchInstanceCount/item.instanceCount).toFixed(2))" />
</div>
</div>
@ -110,13 +138,27 @@ import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomViewer from '@/components/Dicom/DicomViewer'
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 store from '@/store'
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.cornerstone = cornerstone
const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
const maximumSizeInBytes = 1024 * 1024 * 1024 * 6
cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
export default {
components: {
'dicom-viewer': dicomViewer
@ -151,20 +193,25 @@ export default {
firstInstanceId: '',
showDelete: false,
loading: false,
imageList: []
imageList: [],
showSeriesList: [],
currentLoadIns: [],
isFromCRCUpload: false
}
},
created: function() {
requestPoolManager.resetRequestPool()
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
cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
// cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
// cornerstone.events.addEventListener('datasetscachechanged', this.datasetsCacheChanged)
if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '')
}
this.studyId = this.$router.currentRoute.query.studyId
this.isFromCRCUpload = !!this.$router.currentRoute.query.isFromCRCUpload
if (this.type === 'Series') {
// this.initStudy()
this.showDelete = parseInt(this.$router.currentRoute.query.showDelete)
@ -176,50 +223,63 @@ export default {
this.loadStudy()
} else if (this.type === 'Patient') {
this.loadPatientStudy()
}
}
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
},
beforeDestroy() {
requestPoolManager.stopTaskTimer()
window.removeEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
},
methods: {
loadStudy() {
var scope = this
getStudyInfo(scope.studyId).then(data => {
if (data.IsSuccess) {
scope.studyCode = data.Result.StudyCode
scope.modality = data.Result.Modalities
scope.seriesCount = data.Result.SeriesCount
scope.description = data.Result.Description
var url = `/series/list/${scope.studyId}`
scope.getSeriesList(url)
async loadStudy() {
const data = await getStudyInfo(this.studyId)
if (data.IsSuccess) {
if (data.Result) {
this.studyCode = data.Result.StudyCode
this.modality = data.Result.Modalities
this.seriesCount = data.Result.SeriesCount
this.description = data.Result.Description
}
})
const url = `/series/list/${this.studyId}`
this.getSeriesList(url)
}
},
getSeriesList(url) {
var scope = this
getSeriesList(url).then(data => {
async loadPatientStudy() {
try {
const data = await getPatientSeriesList(this.studyId)
if (data.IsSuccess) {
const { Result } = data
var seriesList = []
Result.forEach(function(item) {
Result.forEach((item, index) => {
const imageIds = []
// item.InstanceList.forEach(function(id) {
// imageIds.push(`wadouri:/api/instance/content/${id}`)
// })
// item.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:http://106.14.89.110:7000/instance/content/${id}`)
// })
item.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
item.InstanceInfoList.forEach(i => {
if (i.NumberOfFrames && i.NumberOfFrames > 1) {
for (let j = 0; j < i.NumberOfFrames; j++) {
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 = scope.$router.currentRoute.query.subjectVisitId
var studyId = scope.$router.currentRoute.query.studyId
var trialId = scope.$router.currentRoute.query.trialId
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,
@ -228,77 +288,99 @@ export default {
description: item.Description,
isReading: item.IsReading,
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,
prefetchInstanceCount: 0,
hasLabel: item.HasLabel,
keySeries: item.KeySeries,
tpCode: scope.tpCode,
tpCode: this.tpCode,
loadStatus: false,
imageloadedArr: []
})
})
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: []
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
})
})
this.seriesList = seriesList
if (this.seriesList.length > 0) {
this.$nextTick(() => {
this.loadAllImages()
this.$refs.dicomViewer.loadImageStack(this.seriesList[0])
this.firstInstanceId = this.seriesList[0].imageIds[0]
})
this.loadAllImages()
this.$refs.dicomViewer.loadImageStack(this.seriesList[0], this.labels[this.tpCode])
this.firstInstanceId = this.seriesList[0].imageIds[0]
}
}
} catch (err) {
console.log(err);
console.log(err)
}
},
initSeries() {
var scope = this
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
getInstanceList(seriesId).then(res => {
async getSeriesList(url) {
try {
const data = await getSeriesList(url)
if (data.IsSuccess) {
const { Result } = data
var seriesList = []
Result.forEach((item, index) => {
const imageIds = []
item.InstanceInfoList.forEach(i => {
if (i.NumberOfFrames && i.NumberOfFrames > 1) {
for (let j = 0; j < i.NumberOfFrames; j++) {
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
var seriesInstanceUid = res.Result[0].SeriesInstanceUid
var sliceThickness = res.Result[0].SliceThickness
@ -306,14 +388,29 @@ export default {
var isDeleted = res.Result[0].IsDeleted
var seriesList = []
var imageIds = []
let isExistMutiFrames = false
const instanceInfoList = []
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({
trialId,
subjectVisitId,
studyId,
imageIds: imageIds,
instanceInfoList,
seriesId: seriesId,
seriesUid: seriesInstanceUid,
seriesNumber: seriesNumber,
@ -322,11 +419,12 @@ export default {
description: this.description,
isReading,
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,
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: []
imageloadedArr: [],
isExistMutiFrames: isExistMutiFrames
})
this.seriesList = seriesList
if (this.seriesList.length > 0) {
@ -336,7 +434,9 @@ export default {
this.firstInstanceId = this.seriesList[0].imageIds[0]
})
}
})
} catch (e) {
console.log(e)
}
},
showSeriesImage(e, seriesIndex, series) {
// if (seriesIndex === this.currentSeriesIndex) return
@ -350,16 +450,101 @@ export default {
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
if (!series.loadStatus) {
series.isLoading = true
var p = new Date().getTime()
series.imageIds.map((imageId, i) => {
var priority = ''
if (i === 0) {
priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
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())
// 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 {
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() {
@ -371,13 +556,6 @@ export default {
const seriesInfo = JSON.parse(this.$router.currentRoute.query.series)
var seriesList = []
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) => {
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
var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
var studyId = this.$router.currentRoute.query.studyId
var seriesId = this.$router.currentRoute.query.seriesId
// trialId, subjectVisitId, studyId, seriesId, state
setSeriesStatus(this.trialId, subjectVisitId, studyId, seriesId, 5).then(res => {
try {
const res = await setSeriesStatus(this.trialId, subjectVisitId, studyId, seriesId, 5)
this.loading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
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 = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesReading')
@ -432,24 +613,31 @@ export default {
data.isReading = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
}).then(() => {
const state = data.isReading ? 1 : 2
this.loading = true
setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state).then(res => {
this.loading = false
if (res.IsSuccess) {
data.isReading = !data.isReading
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
}).catch(() => { this.loading = false })
}).catch(() => {})
message = message.replace('yyy', this.$fd('YesOrNo', !data.isReading))
const confirm = await this.$confirm(
message,
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const state = data.isReading ? 1 : 2
this.loading = true
try {
const res = await setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state)
this.loading = false
if (res.IsSuccess) {
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 = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
@ -459,88 +647,76 @@ export default {
data.isDeleted = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
}).then(() => {
const state = data.isDeleted ? 5 : 4
this.loading = true
// var trialId = this.$router.currentRoute.query.trialId
// var subjectVisitId = this.$router.currentRoute.query.subjectVisitId
// var studyId = this.$router.currentRoute.query.studyId
// var seriesId = this.$router.currentRoute.query.seriesId
setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state).then(res => {
this.loading = false
if (res.IsSuccess) {
data.isDeleted = !data.isDeleted
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
}).catch(() => { this.loading = false })
}).catch(() => {})
message = message.replace('yyy', this.$fd('YesOrNo', !data.isDeleted))
const confirm = await this.$confirm(
message,
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const state = data.isDeleted ? 5 : 4
this.loading = true
try {
const res = await setSeriesStatus(data.trialId, data.subjectVisitId, data.studyId, data.seriesId, state)
this.loading = false
if (res.IsSuccess) {
data.isDeleted = !data.isDeleted
this.$message.success(this.$t('common:message:savedSuccessfully'))
window.opener.postMessage({ type: 'refreshSeriesList', data: '' }, window.location)
}
} catch (e) {
console.log(e)
this.loading = false
}
},
loadAllImages() {
const seriesIndex = this.seriesList.findIndex(i => i.loadStatus === false)
if (seriesIndex === -1) return
const series = this.seriesList[seriesIndex]
var priority = new Date().getTime()
this.seriesList.forEach(series => {
series.imageIds.forEach(imageId => {
priority--
// this.load(imageId, series.seriesId, priority)
// 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 {
series.imageIds.map(imageId => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
})
})
}
if (this.imageList.length > 0) {
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() {
if (this.imageList.length > 0) {
requestPoolManager.startTaskTimer()
console.log('loopLoad')
this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
this.imageLoaded(image, res.data.string('x0020000e'))
})
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
})
requestPoolManager.sortTaskPool()
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) {
// const uri = e.detail.uri
const cacheInfo = e.detail.cacheInfo
@ -564,48 +740,44 @@ export default {
return 0
},
cornerstoneImageLoaded(e) {
if (this.firstInstanceId === e.detail.image.imageId && !this.isStartLoad) {
//
this.loadAllImages()
this.isStartLoad = true
// requestPoolManager.executeTask()
cornerstoneimageloadprogress(e) {
const imageId = e.detail.imageId
const percentComplete = e.detail.percentComplete
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
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()
}
// loadedDataSets[uri].dataSet.byteArray.length
// console.log(this.cachedImages.length)
// console.log(cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.getInfo().cacheSizeInBytes)
// const imageId = e.detail.image.imageId
var imageId = e.detail.image.imageId
var seriesUid = e.detail.image.data.string('x0020000e')
var seriesIndex = -1
for (let i = 0; i < this.seriesList.length; ++i) {
if (this.seriesList[i].seriesUid === seriesUid) {
seriesIndex = i
break
if (this.visitTaskId === params.visitTaskId) {
const seriesIndex = params.seriesIndex
var prefetchInstanceCount = this.seriesList[seriesIndex].prefetchInstanceCount
var instanceCount = this.seriesList[seriesIndex].instanceCount
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0 && this.seriesList[seriesIndex].imageloadedArr.length < this.seriesList[seriesIndex].instanceCount) {
const i = this.currentLoadIns.findIndex(i => i.imageId === imageId)
if (i > -1) {
prefetchInstanceCount = prefetchInstanceCount - this.currentLoadIns[i].percentComplete + percentComplete
this.currentLoadIns[i].percentComplete = percentComplete
if (percentComplete === 100) {
this.currentLoadIns.splice(i, 1)
}
} else {
if (percentComplete !== 100) {
this.currentLoadIns.push({ imageId, percentComplete })
}
prefetchInstanceCount = prefetchInstanceCount + percentComplete
}
this.seriesList[seriesIndex].prefetchInstanceCount = prefetchInstanceCount
if (percentComplete >= 100) {
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
}
}
}
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
if (prefetchInstanceCount >= instanceCount * 100) {
this.seriesList[seriesIndex].prefetchInstanceCount = instanceCount * 100
//
this.seriesList[seriesIndex].loadStatus = true
// if (!this.isLoadedAll) {
// this.loadAllImages()
// }
if (!this.isFromCRCUpload) {
this.loadAllImages()
}
}
}
}
@ -710,7 +882,7 @@ export default {
}
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
display: flex;
width: 210px;
width: 200px;
height: 84px;
padding: 1px 2px 1px 8px;
margin: 6px 0 6px 1px;
@ -757,6 +929,41 @@ export default {
color: #D0D0D0;
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 {
width: 300px;
height: 100%;

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -19,7 +19,7 @@
</div>
<!-- 切换访视 -->
<div
v-if="stack.imageRendered && isReadingTaskViewInOrder"
v-if="stack.imageRendered && isReadingTaskViewInOrder === 1"
class="info-visit"
@dblclick.stop="preventDefault($event)"
>
@ -181,7 +181,7 @@ export default {
required: true
},
isReadingTaskViewInOrder: {
type: Boolean,
type: Number,
required: true
},
customWwcTpl: {
@ -222,7 +222,8 @@ export default {
taskBlindName: '',
frame: null,
imageRendered: false,
isExistsClinicalData: false
isExistsClinicalData: false,
isExistMutiFrames: false
// preventCache: true
},
dicomInfo: {
@ -333,7 +334,8 @@ export default {
mounted() {
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', () => {
this.sliderMouseup()
})
@ -477,7 +479,7 @@ export default {
},
methods: {
goViewer(e) {
console.log(this.$refs['sliderBox'].clientHeight)
// 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)
@ -546,7 +548,7 @@ export default {
},
mouseUp(e) {
console.log('mouseUp')
// console.log('mouseUp')
if (this.readingTaskState >= 2) return
this.image = e.detail.image
this.getToolStateInfo(e)
@ -672,7 +674,7 @@ export default {
this.sliderInfo.isMove = false
},
getMeasureData() {
console.log('getMeasureData')
// console.log('getMeasureData')
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
@ -757,7 +759,7 @@ export default {
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
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
for (var m = 0; m < this.measuredTools.length; m++) {
var toolType = this.measuredTools[m]
@ -814,7 +816,7 @@ export default {
}
},
stackScrollCallback(e) {
console.log('stackScrollCallback')
// console.log('stackScrollCallback')
const { detail } = e
if (this.isScrollSync && this.currentDicomCanvasIndex === this.canvasIndex) {
this.scrollSyncInfo.canvasIndex = this.canvasIndex
@ -879,7 +881,6 @@ export default {
return seriesList[seriesIdx].loadStatus ? 1 : 0
},
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)
if (idx === -1) return
this.measureData = this.visitTaskList[idx].MeasureData
@ -898,9 +899,7 @@ export default {
} else {
cornerstoneTools.setToolEnabledForElement(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))) {
const toolState = ToolStateManager.getImageIdToolState(e.detail.image.imageId, data.MeasureData.type)
if (toolState && toolState.data.length > 0) {
var idx = toolState.data.findIndex(item => item.uuid === data.MeasureData.data.uuid)
@ -987,7 +986,7 @@ export default {
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
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
for (let t = 0; t < this.measuredTools.length; t++) {
var toolType = this.measuredTools[t]
@ -998,7 +997,7 @@ export default {
if (i > -1) {
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
if (idx > -1) {
console.log('mouseClick')
// console.log('mouseClick')
DicomEvent.$emit('setCollapseActive', this.measureData[idx])
if (this.readingTaskState < 2) {
const measureData = {}
@ -1040,7 +1039,7 @@ export default {
loadImageStack(dicomSeries) {
return new Promise(resolve => {
this.isCurrentTask = dicomSeries.isCurrentTask
this.isBaseline = dicomSeries.isBaseline
this.isBaseline = dicomSeries.isBaseLineTask
this.readingTaskState = dicomSeries.readingTaskState
if (this.isCurrentTask && this.readingTaskState < 2) {
this.activeTool = 1
@ -1055,7 +1054,7 @@ export default {
this.stack.studyId = dicomSeries.studyId
this.stack.seriesNumber = dicomSeries.seriesNumber
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.firstImageLoading = true
this.stack.visitTaskId = dicomSeries.visitTaskId
@ -1066,6 +1065,7 @@ export default {
this.stack.sliceThickness = dicomSeries.sliceThickness
this.stack.instanceCount = dicomSeries.instanceCount
this.stack.isExistsClinicalData = dicomSeries.isExistsClinicalData
this.stack.isExistMutiFrames = dicomSeries.isExistMutiFrames
// this.measuredData = dicomSeries.measuredData
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId)
this.stack.visitTaskNum = this.visitTaskList[idx].VisitTaskNum
@ -1086,18 +1086,18 @@ export default {
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
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
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
cornerstone.enable(element)
element.tabIndex = 0
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 p = parseInt(new Date().getTime())
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{
@ -1110,22 +1110,27 @@ export default {
// }
// resolve()
// })
this.loading = true
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(async image => {
await scope.onFirstImageLoaded(image)
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
await scope.onFirstImageLoaded(image)
}
scope.loading = false
resolve()
})
.catch((error) => {
if (error.error && error.error.message) {
this.$alert(error.error.message)
}
scope.loading = false
resolve()
})
})
},
onFirstImageLoaded(image) {
console.log('onFirstImageLoaded')
return new Promise(resolve => {
// 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)
@ -1195,15 +1200,15 @@ export default {
const imageInfo = this.getInstanceInfo(image.imageId)
var instanceId = imageInfo.instanceId
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.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
this.resetWwwc()
// this.resetWwwc()
resolve()
})
},
onNewImage(e) {
console.log('cornerstonenewimage')
// console.log('cornerstonenewimage')
if (this.isCurrentTask && this.readingTaskState < 2) {
this.resetHideMeasureArr()
}
@ -1240,6 +1245,12 @@ export default {
if (this.dicomInfo.thick) {
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() {
const canvas = this.canvas.querySelector('canvas')
@ -1264,7 +1275,7 @@ export default {
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
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) {
this.getOrientationMarker(e.detail.element)
//
@ -1316,20 +1327,20 @@ export default {
var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport
//
console.log('completed')
// console.log('completed')
this.activeTool = 1
this.activeToolName = ''
var { imageId } = element.image
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
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') {
const measureData = {}
measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId
measureData.instanceId = instanceId
measureData.frame = this.stack.frame ? this.stack.frame : 0
measureData.frame = this.stack.frame
measureData.data = e.detail.measurementData
measureData.type = e.detail.toolName
measureData.thick = this.dicomInfo.thick
@ -1434,7 +1445,7 @@ export default {
},
onMeasurementmodified(e) {
//
console.log('modified')
// console.log('modified')
if (this.readingTaskState >= 2) return
const { measurementData, toolType } = e.detail
var element = cornerstone.getEnabledElement(this.canvas)
@ -1443,7 +1454,8 @@ export default {
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
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 idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) {
@ -1559,8 +1571,10 @@ export default {
resetViewport() {
this.toolState.viewportInvert = false
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
if (this.originalMarkers.length > 0) {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
var image = cornerstone.getImage(this.canvas)
cornerstone.setViewport(
this.canvas,
@ -1619,18 +1633,19 @@ export default {
}
},
toggleClipPlay() {
if (this.toolState.clipPlaying) {
toggleClipPlay(isPlay) {
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)
this.toolState.clipPlaying = false
return
}
this.toolState.clipPlaying = true
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
cornerstoneTools.getToolState(
this.canvas,
'playClip'
).data[0].loop = false
},
setFps(fps) {
this.dicomInfo.fps = fps
@ -1639,7 +1654,7 @@ export default {
resetWwwc() {
this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas)
viewport.invert = false
// viewport.invert = false
var image = cornerstone.getImage(this.canvas)
viewport.voi.windowWidth = image.windowWidth
viewport.voi.windowCenter = image.windowCenter
@ -1675,8 +1690,10 @@ export default {
},
resetRotate() {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
if (this.originalMarkers.length > 0) {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
var viewport = cornerstone.getViewport(this.canvas)
viewport.hflip = false
viewport.vflip = false
@ -1691,23 +1708,25 @@ export default {
}
},
setRotate(hflip, vflip, angle, type) {
var markers = [...this.orientationMarkers]
if (type === 2) {
//
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 3) {
//
this.orientationMarkers[1] = markers[3]
this.orientationMarkers[3] = markers[1]
} else if (type === 4) {
// 90
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 90
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
if (this.orientationMarkers.length > 0) {
var markers = [...this.orientationMarkers]
if (type === 2) {
//
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 3) {
//
this.orientationMarkers[1] = markers[3]
this.orientationMarkers[3] = markers[1]
} else if (type === 4) {
// 90
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 90
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
}
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas)
if (hflip) viewport.hflip = !viewport.hflip
if (vflip) viewport.vflip = !viewport.vflip
@ -1716,9 +1735,8 @@ export default {
},
saveImage() {
let timestamp = Date.now()
// var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
cornerstoneTools.SaveAs(this.canvas, `${this.subjectCode}_${this.stack.taskBlindName}_${timestamp}.png`)
var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
},
fitToWindow() {
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) {
e.stopImmediatePropagation()
e.stopPropagation()
@ -1927,15 +1956,6 @@ export default {
e.stopImmediatePropagation()
e.stopPropagation()
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
</div>
</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">
A
</div>
@ -280,6 +280,54 @@
<div class="text">{{ tool.text }}</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">
<div class="tool-wrapper">
@ -292,7 +340,7 @@
<div class="text">{{ $t('trials:reading:button:reset') }}</div>
</div>
</el-tooltip>
<div style="margin-left:auto;">
<div style="padding:5px">
<!-- 手册 -->
@ -337,41 +385,63 @@
</div>
</div>
<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
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"
/>
<RecistQuestionList
v-else-if="CriterionType === 1"
ref="measurementList"
:question-form-change-state="questionFormChangeState"
:question-form-change-num="questionFormChangeNum"
:is-show="isShow"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
/>
<h2 v-else style="color:#ddd">
Developing...
</h2>
</div>
<div v-if="iseCRFShowInDicomReading && currentReadingTaskState < 2" class="form-footer">
<el-button
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<el-button
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>
@ -438,6 +508,21 @@
<Manuals :trial-id="trialId" />
</div>
</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>
</template>
<script>
@ -466,6 +551,12 @@ import WL from './WL'
import Others from './Others'
import DicomEvent from './DicomEvent'
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 {
name: 'DicomViewer',
components: {
@ -479,7 +570,8 @@ export default {
RecistQuestionList,
PCWGQuestionList,
RecistBMQuestionList,
IRecistQuestionList
IRecistQuestionList,
SignForm
},
props: {
isShow: {
@ -499,13 +591,17 @@ export default {
required: true
},
isReadingTaskViewInOrder: {
type: Boolean,
type: Number,
required: true
},
isExistsManual: {
type: Boolean,
required: true
},
iseCRFShowInDicomReading: {
type: Boolean,
required: true
},
questionFormChangeState: {
type: Boolean,
default() {
@ -603,7 +699,13 @@ export default {
digitPlaces: 2,
activeCanvasWW: 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: {
immediate: true,
handler(v) {
if (v && v.isCurrentTask && this.studyList.length === 0) {
this.activeTaskInfo.taskName = v.taskBlindName
this.activeTaskInfo.visitTaskId = v.visitTaskId
const i = this.visitTaskList.findIndex(i => i.VisitTaskId === v.visitTaskId)
if (i < 0) return
this.activeTaskInfo.visitTaskIndex = i
var studyList = this.visitTaskList[i].StudyList || []
studyList = studyList.filter(i => !i.IsCriticalSequence && i.Modalities.indexOf('CT') !== -1 && i.Modalities.indexOf('PT') !== -1)
if (studyList.length === 0) return
this.studyList = studyList
}
// console.log('activeSeries', v)
// if (v && v.isCurrentTask && this.studyList.length === 0) {
// this.activeTaskInfo.taskName = v.taskBlindName
// this.activeTaskInfo.visitTaskId = v.visitTaskId
// const i = this.visitTaskList.findIndex(i => i.VisitTaskId === v.visitTaskId)
// if (i < 0) return
// this.activeTaskInfo.visitTaskIndex = i
// var studyList = this.visitTaskList[i].StudyList || []
// studyList = studyList.filter(i => !i.IsCriticalSequence && i.Modalities.indexOf('CT') !== -1 && i.Modalities.indexOf('PT') !== -1)
// if (studyList.length === 0) return
// this.studyList = studyList
// }
}
},
imageQualityIssues: {
immediate: true,
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: '' }]
} 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: '' }]
} else if (this.CriterionType === 19) {
this.measuredTools = []
} else if (this.CriterionType === 20) {
this.measuredTools = []
}
this.rotateList[0] = '1'
this.colorList[0] = ''
@ -717,6 +835,7 @@ export default {
)
var canvas = await html2canvas(divForDownloadViewport)
var base64Str = canvas.toDataURL('image/png', 1)
console.log('getScreenshots')
callback(base64Str)
}, 50)
}
@ -772,6 +891,10 @@ export default {
if (!this.petctWindow) return
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) => {
if (!this.petctWindow) return
this.petctWindow.postMessage({ type: 'setReadingState', data: data }, window.location)
@ -809,28 +932,30 @@ export default {
})
},
methods: {
getWwcTpl() {
const loading = this.$loading({ fullscreen: true })
getUserWLTemplateList().then(res => {
async getWwcTpl() {
// const loading = this.$loading({ fullscreen: true })
try {
const res = await getUserWLTemplateList()
this.customWwcTpl = []
res.Result.map(i => {
this.customWwcTpl.push({ label: i.TemplateName, wc: i.WL, ww: i.WW })
})
this.wwwcArr = [...this.defaultWwwc, ...this.customWwcTpl]
loading.close()
}).catch(() => { loading.close() })
} catch (e) {
console.log(e)
}
},
getHotKeys() {
const loading = this.$loading({ fullscreen: true })
getDoctorShortcutKey({ imageToolType: 0 }).then(res => {
async getHotKeys() {
// const loading = this.$loading({ fullscreen: true })
try {
const res = await getDoctorShortcutKey({ imageToolType: 0 })
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.bindHotKey()
loading.close()
}).catch(() => {
loading.close()
})
} catch (e) {
console.log(e)
}
},
resetHotkeyList(arr) {
this.hotKeyList = []
@ -853,7 +978,7 @@ export default {
var container = this.$refs['container']
// window.addEventListener
container.addEventListener('keydown', event => {
console.log(event)
// console.log(event)
event.preventDefault()
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/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 (series.isCurrentTask && series.readingTaskState < 2) {
@ -1010,10 +1136,13 @@ export default {
})
},
loadImageStack(dicomSeries) {
this.clipPlaying = false
this.fps = 15
this.canvasObj[this.currentDicomCanvasIndex] = dicomSeries
this.$nextTick(() => {
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 (dicomSeries.isCurrentTask && dicomSeries.readingTaskState < 2) {
this.$nextTick(() => {
@ -1074,7 +1203,8 @@ export default {
// }
this.$nextTick(() => {
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)
if (this.currentDicomCanvasIndex === this.maxCanvas - 1) {
@ -1149,7 +1279,8 @@ export default {
var promiseArr = []
for (let i = 0; i < this.maxCanvas && i < seriesStack.length; 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(() => {
// this.activateDicomCanvas(this.currentDicomCanvasIndex)
@ -1181,7 +1312,7 @@ export default {
var firstAddSeries = null
var currentAddSeries = null
if (this.isReadingTaskViewInOrder) {
if (this.isReadingTaskViewInOrder === 1) {
//
// 访
var firstAddVisitTaskId = null
@ -1252,12 +1383,14 @@ export default {
for (let i = 0; i < this.maxCanvas; i++) {
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.activeSeries = currentAddSeries
store.dispatch('reading/setActiveSeries', currentAddSeries)
} 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)
@ -1331,7 +1464,9 @@ export default {
var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId)
if (seriesIdx > -1) {
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) {
series.imageIdIndex = instanceIdx
seriesInfo = series
@ -1687,6 +1822,31 @@ export default {
}
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) {
this.$refs['measurementList'].setMeasuredData(data)
@ -1779,7 +1939,109 @@ export default {
previewManuals() {
this.isFullscreen = false
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>
@ -1832,7 +2094,7 @@ export default {
flex-direction: column;
justify-content: center;
align-items: center;
margin-right: 30px;
margin-right: 20px;
.icon{
padding: 5px;
border: 1px solid #404040;
@ -1851,6 +2113,39 @@ export default {
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{
background-color: #607d8b;
}
@ -1963,9 +2258,22 @@ export default {
.form-container{
// box-sizing: border-box;
width: 350px;
height: 100%;
// height: 100vh;
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{
box-sizing: border-box;

View File

@ -56,22 +56,25 @@ export default {
this.getHotkeys()
},
methods: {
getHotkeys(isReset = false) {
async getHotkeys(isReset = false) {
this.loading = true
this.hotKeyList = []
getDoctorShortcutKey({ imageToolType: this.readingTool }).then(res => {
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 })
})
if (isReset) {
this.$emit('reset', this.hotKeyList)
try {
const res = await getDoctorShortcutKey({ imageToolType: this.readingTool })
if (res.IsSuccess) {
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 })
})
if (isReset) {
this.$emit('reset', this.hotKeyList)
}
}
this.loading = false
}).catch(() => {
} catch (e) {
this.loading = false
})
}
},
handleSave() {
async handleSave() {
var params = {
imageToolType: this.readingTool,
shortcutKeyList: []
@ -86,17 +89,15 @@ export default {
emptyLabel = item.label
break
} else {
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 }
)
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 })
}
}
if (isExistEmptyText) {
@ -112,43 +113,40 @@ export default {
})
} else {
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
setShortcutKey(params).then(res => {
this.$emit('reset', this.hotKeyList)
// this.$emit('close')
try {
const res = await setShortcutKey(params)
if (res.IsSuccess) {
this.$emit('reset', this.hotKeyList)
}
this.loading = false
}).catch(() => {
} catch (e) {
this.loading = false
})
}
}
},
handleReset() {
async handleReset() {
// ''
this.$confirm(this.$t('trials:hotkeys:message:confirmReset'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
this.loading = true
restoreDefaultShortcutKey({ imageToolType: this.readingTool }).then(res => {
this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // ''
this.getHotkeys(true)
}).catch(() => { this.loading = false })
})
.catch(action => {})
const confirm = await this.$confirm(
this.$t('trials:hotkeys:message:confirmReset'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
try {
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) {
for (const item of this.hotKeyList) {

View File

@ -1,11 +1,21 @@
<template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
<div class="measurement-wrapper">
<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="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="lesions">
<Questions
@ -29,7 +39,7 @@
class="title"
>
{{ 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 v-else class="title">
{{ item.QuestionName }}
@ -157,6 +167,7 @@
</template>
<script>
import { splitLesion } from '@/api/trials'
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent'
import store from '@/store'
import { mapGetters } from 'vuex'
@ -192,7 +203,6 @@ export default {
},
data() {
return {
height: window.innerHeight - 140,
questions: [],
activeName: '',
activeItem: {
@ -237,7 +247,8 @@ export default {
}
},
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)
this.criterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => {
@ -257,8 +268,6 @@ export default {
DicomEvent.$on('split', measureData => {
this.handleSplit(measureData.RowId, measureData.QuestionId)
})
window.addEventListener('resize', this.setHeight)
},
beforeDestroy() {
DicomEvent.$off('setCollapseActive')
@ -445,9 +454,6 @@ export default {
} catch (e) { console.log(e) }
})
},
setHeight() {
this.height = window.innerHeight - 140
},
getQuestionAnswer(questions, questionMark, answers) {
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) {
@ -577,15 +583,15 @@ export default {
}
}
},
split(rowId, questionId) {
async split(rowId, questionId) {
const loading = this.$loading({ fullscreen: true })
var params = {
visitTaskId: this.visitTaskId,
questionId: questionId,
rowId: rowId
}
splitLesion(params).then(async res => {
loading.close()
try {
var params = {
visitTaskId: this.visitTaskId,
questionId: questionId,
rowId: rowId
}
await splitLesion(params)
await this.getReadingQuestionAndAnswer()
this.$nextTick(() => {
this.tableQuestions.forEach(item => {
@ -595,7 +601,11 @@ export default {
})
})
})
})
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
isCanActiveTool(toolName) {
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 })
questionsObj.measureData.data.remark = lesionMark
lesionObj.MarkTool = questionsObj.measureData.type
lesionObj.MeasureData = JSON.stringify(questionsObj.measureData)
}
@ -1068,6 +1077,39 @@ export default {
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()
@ -1135,11 +1177,28 @@ export default {
</script>
<style lang="scss" scoped>
.measurement-wrapper{
height: 100%;
overflow-y: auto;
// overflow: hidden;
.container{
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{
padding: 5px;

View File

@ -21,7 +21,7 @@
</div>
<div class="right-wrapper">
<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>
@ -44,26 +44,31 @@ export default {
},
fileList: [],
loading: false,
currentUser: zzSessionStorage.getItem('userName')
currentUser: zzSessionStorage.getItem('userName'),
COMPANY:process.env.VUE_APP_COMPANY_NAME
}
},
mounted() {
this.getList()
},
methods: {
getList() {
async getList() {
this.loading = true
var param = {
trialId: this.trialId
}
getManualList(param).then(res => {
this.fileList = res.Result
if (this.fileList.length > 0) {
this.preview(this.fileList[0])
try {
var param = {
trialId: this.trialId
}
const res = await getManualList(param)
if (res.IsSuccess) {
this.fileList = res.Result
if (this.fileList.length > 0) {
this.preview(this.fileList[0])
}
}
this.loading = false
}).catch(() => { this.loading = false })
} catch (e) {
this.loading = false
}
},
preview(file) {
this.$set(this.selected, 'filePath', file.Path)

View File

@ -76,9 +76,10 @@
</div>
</template>
<script>
import { getTableAnswerRowInfoList } from '@/api/trials'
import { on, off } from 'element-ui/src/utils/dom'
import { rafThrottle, isFirefox } from 'element-ui/src/utils/util'
import store from '@/store'
// import store from '@/store'
const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel'
var ctx = '' //
export default {
@ -223,15 +224,26 @@ export default {
return new Promise(async resolve => {
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
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)
const res = await getTableAnswerRowInfoList(this.visitTaskId)
res.Result.forEach(el => {
if (!el.IsDicomReading) {
if (el.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()
})
},

View File

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

View File

@ -36,27 +36,31 @@ export default {
this.initForm()
},
methods: {
initForm() {
async initForm() {
this.loading = true
getAutoCutNextTask().then(async res => {
this.form.AutoCutNextTask = res.Result.AutoCutNextTask
this.loading = false
}).catch(() => {
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
})
try {
const res = await getAutoCutNextTask()
if (res.IsSuccess) {
this.form.AutoCutNextTask = res.Result.AutoCutNextTask
}
})
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}"
@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)) }}
</template>
</el-input>
@ -296,7 +296,7 @@ export default {
} else if (!reg.test(value) || (parseInt(value) > 99 || parseInt(value) <= 0)) {
callback(new Error(this.$t('trials:readingPGWC:warnning:msg1')))
} 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 {
callback()
}
@ -484,8 +484,8 @@ export default {
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionState = Number(this.getQuestionVal(7))
const lesionNum = Number(this.getQuestionVal(11))
const lesionState = this.getQuestionVal(7)
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 })
},
@ -547,8 +547,8 @@ export default {
this.$set(this.questionForm, 'MeasureData', measureData)
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionState = Number(this.getQuestionVal(7))
const lesionNum = Number(this.getQuestionVal(11))
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: this.questionForm })
this.toolType = measureData.type
@ -572,10 +572,15 @@ export default {
}
},
getQuestionVal(questionMark) {
var idx = this.questions.findIndex(i => i.QuestionMark === questionMark)
const idx = this.questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) {
var questionId = this.questions[idx].Id
return this.questionForm[questionId]
const questionId = this.questions[idx].Id
const answer = this.questionForm[questionId]
if (isNaN(parseFloat(answer))) {
return answer
} else {
return parseFloat(answer)
}
} else {
return ''
}
@ -619,82 +624,83 @@ export default {
// Blob
return new Blob([bytesCode], { type: imgtype })
},
handleSave() {
this.$refs.measurementForm.validate(async valid => {
if (!valid) return
var lesionState = this.getQuestionVal(7)
var measureData = this.questionForm.MeasureData
// 线
if (!this.isBaseLineTask) {
// 2
// 使2
if (this.lesionType === 2 && lesionState === 2) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg2'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
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
}
async handleSave() {
const valid = await this.$refs.measurementForm.validate()
if (!valid) return
var lesionState = this.getQuestionVal(7)
var measureData = this.questionForm.MeasureData
// 线
if (!this.isBaseLineTask) {
// 2
// 使2
if (this.lesionType === 2 && lesionState === 2) {
if (!(measureData && measureData.type === 'ArrowAnnotate')) {
this.$confirm(this.$t('trials:readingPGWC:warnning:msg2'), {
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 => {
// 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 })
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 = ''
if (val && measureData) {
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 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,
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 })
DicomEvent.$emit('getMeasureData')
this.$emit('close')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('setMeasuredToolsPassive')
} catch (e) {
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))
const res = await submitTableQuestion(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.currentMarkTool = measureData ? measureData.type : ''
this.$set(this.questionForm, 'saveTypeEnum', 2)
this.originalQuestionForm = { ...this.questionForm }
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')
})
.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 })
}
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 = this.getQuestionVal(7)
const lesionNum = this.getQuestionVal(11)
this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, saveTypeEnum: this.questionForm.saveTypeEnum, lesionState, lesionNum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
DicomEvent.$emit('refreshStudyListMeasureData')
this.$emit('close')
DicomEvent.$emit('getReportInfo', true)
DicomEvent.$emit('setMeasuredToolsPassive')
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() {
if (!this.questionForm.RowId) {
@ -866,7 +881,7 @@ export default {
this.$set(this.questionForm, stateId, 4)
const lesionPart = this.getQuestionVal(8)
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 })
}
}

View File

@ -1,11 +1,21 @@
<template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
<div class="measurement-wrapper">
<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="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="lesions">
<Questions
@ -64,7 +74,7 @@
{{ item.TableQuestions.Answers[i].lesionType }}
</div>
<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>
@ -101,6 +111,7 @@
</template>
<script>
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent'
import Questions from './../Questions'
import QuestionForm from './QuestionForm'
@ -136,7 +147,6 @@ export default {
},
data() {
return {
height: window.innerHeight - 140,
questions: [],
activeName: '',
activeItem: {
@ -184,7 +194,8 @@ export default {
}
},
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)
this.criterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => {
@ -200,8 +211,6 @@ export default {
callback(list)
console.log('getAllUnSaveLesions')
})
window.addEventListener('resize', this.setHeight)
},
beforeDestroy() {
DicomEvent.$off('setCollapseActive')
@ -687,6 +696,102 @@ export default {
this.activeItem.activeRowIndex = null
this.activeItem.activeCollapseId = null
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>
.measurement-wrapper{
height: 100%;
overflow-y: auto;
// overflow: hidden;
.container{
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{
padding: 5px;

View File

@ -13,46 +13,86 @@
{{ language==='en'?question.GroupEnName:question.GroupName }}
</h4>
</div>
<template v-else-if="((question.QuestionType === 56 || question.QuestionType === 57) && question.IsBaseLineTask)" />
<template v-else>
<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}`"
:prop="question.Id"
:rules="[
{ 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']},
]"
: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
v-if="question.Type==='input'"
v-else-if="question.Type==='input'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
@change="((val)=>{formItemChange(val, question)})"
/>
<!-- 多行文本输入框 -->
<el-input
v-if="question.Type==='textarea'"
v-else-if="question.Type==='textarea'"
v-model="questionForm[question.Id]"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
maxlength="500"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
@change="((val)=>{formItemChange(val, question)})"
/>
<!-- 下拉框 -->
<el-select
v-if="question.Type==='select'"
v-else-if="question.Type==='select'"
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
@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">
<el-option
v-for="item in organList"
@ -61,6 +101,50 @@
:value="item[question.DataTableColumn]"
/>
</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">
<el-option
v-for="item of $d[question.DictionaryCode]"
@ -88,18 +172,11 @@
</el-select>
<!-- 单选 -->
<el-radio-group
v-if="question.Type==='radio'"
v-else-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
@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">
<el-radio
v-for="item of $d[question.DictionaryCode]"
@ -121,7 +198,7 @@
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-if="question.Type==='checkbox'"
v-else-if="question.Type==='checkbox'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || isFirstChangeTask"
>
@ -134,16 +211,45 @@
</el-checkbox>
</el-checkbox-group>
<!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" -->
<el-input-number
v-if="question.Type==='number'"
<!-- <el-input-number
v-else-if="question.Type==='number'"
v-model="questionForm[question.Id]"
: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
v-if="question.Type==='upload'"
:action="accept"
v-else-if="question.Type==='upload'"
action
:accept="accept"
:limit="question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
@ -158,7 +264,6 @@
<div slot="file" slot-scope="{file}">
<img
class="el-upload-list__item-thumbnail"
crossOrigin="Anonymous"
:src="OSSclientConfig.basePath + file.url"
alt=""
>
@ -209,7 +314,8 @@
</div>
</template>
<script>
import { uploadReadingAnswerImage } from '@/api/trials'
// import { uploadReadingAnswerImage } from '@/api/trials'
import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex'
export default {
name: 'QuestionItem',
@ -245,7 +351,8 @@ export default {
accept: '.png,.jpg,.jpeg',
imgVisible: false,
imageUrl: '',
urls: []
urls: [],
digitPlaces: 2
}
},
computed: {
@ -271,11 +378,19 @@ export default {
})
}
}
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
},
methods: {
formItemChange(v, question) {
// if (parseInt(v) !== 5) {
// return
// }
if (question.Childrens.length > 0) {
this.resetChild(question.Childrens)
} else {
this.$emit('setFormItemData', { key: question.Id, val: v })
}
},
resetChild(obj) {
@ -292,7 +407,28 @@ export default {
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
const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'),
@ -301,18 +437,12 @@ export default {
text: 'Loading',
spinner: 'el-icon-loading'
})
const formData = new FormData()
formData.append('file', param.file)
uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
if (res.IsSuccess) {
this.fileList.push({ url: `${res.Result.Path}` })
this.urls.push(res.Result.Path)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
}
loading.close()
}).catch(() => {
loading.close()
})
var file = await this.fileToBlob(param.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.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
loading.close()
},
handleBeforeUpload(file) {
//
@ -335,7 +465,7 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = file.url
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
},
//
@ -353,19 +483,25 @@ export default {
margin-bottom: 0px;
}
.disabled{
>>>.el-upload--picture-card {
/deep/ .el-upload--picture-card {
display: none;
}
}
.uploadWrapper{
display: flex;
flex-direction: column;
flex-direction: column !important;
align-items: flex-start;
}
>>>.el-input.is-disabled .el-input__inner{
/deep/ .el-input.is-disabled .el-input__inner{
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;
}
</style>

View File

@ -19,8 +19,9 @@
/>
<el-form-item v-if="readingTaskState < 2 && !isFirstChangeTask">
<div style="text-align:right">
<el-button size="mini" :disabled="!questionFormChangeState" :type="questionFormChangeState ? 'primary' : null" @click="handleSave">{{ $t('common:button:save') }}</el-button>
<div class="ecrf-footer">
<!-- <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>
</el-form-item>
</el-form>
@ -29,8 +30,9 @@
</template>
<script>
import { saveImageQuality } from '@/api/trials'
// import { uploadPrintscreen } from '@/api/reading'
import { saveTaskQuestion, getSplenicState, getSplenicVerify, getCanChooseNotMerge, getDicomReadingQuestionAnswer } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import QuestionItem from './QuestionItem'
import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex'
@ -52,6 +54,18 @@ export default {
isFirstChangeTask: {
type: Boolean,
default: false
},
groupClassify: {
type: Number,
default: null
},
isQulityIssues: {
type: Boolean,
default: true
},
questionType: {
type: Number,
default: 0
}
},
data() {
@ -61,7 +75,20 @@ export default {
questionForm: {},
readingTaskState: 2,
visitTaskId: '',
imageQualityId: ''
imageQualityId: '',
imageQualityIssuesId: '',
measurements: [],
spleenStatusId: '',
spleenLengthId: '',
spleenCommentsId: '',
spleenTopId: '',
spleenBottomId: '',
isBaseLineTask: false,
criterionType: null,
spleenInfo: null,
calculateSpleenStatus: '',
formChanged: false,
digitPlaces: 2
}
},
computed: {
@ -72,7 +99,9 @@ export default {
deep: true,
immediate: false,
handler(v) {
DicomEvent.$emit('questionFormChange', true)
if (this.isQulityIssues) {
DicomEvent.$emit('questionFormChange', true)
}
}
},
currentReadingTaskState: {
@ -85,45 +114,120 @@ export default {
}
},
mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.criterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setReadingState', readingTaskState => {
this.readingTaskState = readingTaskState
})
DicomEvent.$on('handleSaveQuestions', readingTaskState => {
this.handleSave()
})
if (this.groupClassify === 3) {
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() {
DicomEvent.$off('setReadingState')
if (this.groupClassify === 3) {
DicomEvent.$off('addAnnotation')
DicomEvent.$off('removeAnnotation')
DicomEvent.$off('saveAnnotation')
DicomEvent.$off('locateAnnotation')
}
},
methods: {
async getQuestions(visitTaskId) {
async getQuestions(visitTaskId, isRefresh = false) {
var isChangeVisitTask = this.visitTaskId !== visitTaskId
this.visitTaskId = visitTaskId
// const loading = this.$loading({ fullscreen: true })
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === visitTaskId)
var qs = []
if (idx > -1) {
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
var questions = this.visitTaskList[idx].Questions
questions.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
if (this.groupClassify === 3) {
this.measurements = []
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)
if (v.QuestionType === 44) {
//
//
this.imageQualityId = v.Id
// 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) {
this.setChild(v.Childrens)
}
})
this.questions = questions
qs.push(v)
}
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()
},
setChild(obj) {
obj.forEach(i => {
i.IsBaseLineTask = this.isBaseLineTask
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
if (i.QuestionType === 44) {
@ -131,95 +235,673 @@ export default {
this.imageQualityId = i.Id
// 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) {
this.setChild(i.Childrens)
}
})
},
handleSave() {
this.$refs['questions'].validate((valid) => {
this.$refs['questions'].validate(async(valid) => {
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
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) {
answers.push({ id: k, answer: this.questionForm[k] })
if (k === this.imageQualityId) {
imageQuality = this.questionForm[k]
if (k === question.Id) {
answers.push({ id: k, answer: this.questionForm[k] })
break
}
}
var params = {
visitTaskId: this.visitTaskId,
answers: answers
answers,
questionMarkInfoList
}
saveImageQuality(params).then(async res => {
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)
this.loading = false
DicomEvent.$emit('questionFormChange', false)
DicomEvent.$emit('getReportInfo', true)
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(() => {
})
}
const qsType = question.QuestionType === 60 ? 4 : question.QuestionType === 61 ? 5 : null
await saveTaskQuestion(qsType, params)
this.$message.success(this.$t('common:message:savedSuccessfully'))
await this.setQuestions()
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
}
}).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) {
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) {
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>
<style lang="scss" scoped>
.ecrf-wrapper{
>>>.el-form-item__label{
/deep/ .el-form-item__label{
color: #c3c3c3;
text-align: left;
}
>>>.el-input__inner{
/deep/ .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
>>>.el-textarea__inner{
/deep/ .el-textarea__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
>>>.el-form-item{
/deep/ .el-form-item{
display: flex;
flex-direction: row;
justify-content: flex-start;
flex-wrap: wrap;
}
>>>.el-form-item__content{
/deep/ .el-form-item__content{
flex: 1;
}
>>>.el-button--mini, .el-button--mini.is-round {
/deep/ .el-button--mini, .el-button--mini.is-round {
padding: 7px 10px;
}
.el-form-item__content
/deep/ .el-form-item__content
.el-select{
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>

View File

@ -57,6 +57,7 @@
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
:is-exists-manual="isExistsManual"
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
@previewCD="previewCD"
/>
</div>
@ -72,6 +73,25 @@ import DicomEvent from './DicomEvent'
import store from '@/store'
import { getToken } from '@/utils/auth'
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 {
name: 'ReadPage',
components: {
@ -112,13 +132,17 @@ export default {
required: true
},
isReadingTaskViewInOrder: {
type: Boolean,
type: Number,
required: true
},
isExistsManual: {
type: Boolean,
required: true
},
iseCRFShowInDicomReading: {
type: Boolean,
required: true
},
questionFormChangeState: {
type: Boolean,
default() {
@ -210,14 +234,20 @@ export default {
this.$refs[this.activeTaskVisitId][0].selectSeries(data)
})
})
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
})
},
beforeDestroy() {
cornerstone.imageCache.purgeCache()
DicomEvent.$off('getNextVisitInfo')
DicomEvent.$off('toggleSeries')
DicomEvent.$off('isCanActiveNoneDicomTool')
DicomEvent.$off('removeNoneDicomMeasureData')
DicomEvent.$off('addNoneDicomMeasureData')
DicomEvent.$off('selectSeries')
window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() })
},
methods: {
async getVisitInfo() {
@ -400,7 +430,7 @@ export default {
idx > -1 ? obj = seriesList[idx] : ''
}
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
}
return obj
@ -464,7 +494,10 @@ export default {
var seriesIdx = studyList[studyIdx].SeriesList.findIndex(s => s.seriesId === seriesId)
if (seriesIdx > -1) {
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) {
series.imageIdIndex = instanceIdx
// series.studyIndex = studyIdx
@ -485,6 +518,16 @@ export default {
seriesInfo = this.getLinkedSeries(baseSeries, visitTaskId, visitTaskIdx)
}
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>
<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">
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" />
@ -122,6 +133,7 @@
</template>
<script>
import { splitLesion } from '@/api/trials'
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent'
import store from '@/store'
import { mapGetters } from 'vuex'
@ -157,7 +169,6 @@ export default {
},
data() {
return {
height: window.innerHeight - 140,
questions: [],
activeName: '',
activeItem: {
@ -201,7 +212,8 @@ export default {
}
},
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)
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => {
@ -221,8 +233,6 @@ export default {
DicomEvent.$on('split', measureData => {
this.handleSplit(measureData.RowId, measureData.QuestionId)
})
window.addEventListener('resize', this.setHeight)
},
beforeDestroy() {
DicomEvent.$off('setCollapseActive')
@ -403,9 +413,6 @@ export default {
} catch (e) { console.log(e) }
})
},
setHeight() {
this.height = window.innerHeight - 140
},
getQuestionAnswer(questions, questionMark, answers) {
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) {
@ -503,15 +510,15 @@ export default {
}
}
},
split(rowId, questionId) {
async split(rowId, questionId) {
const loading = this.$loading({ fullscreen: true })
var params = {
visitTaskId: this.visitTaskId,
questionId: questionId,
rowId: rowId
}
splitLesion(params).then(async res => {
loading.close()
try {
var params = {
visitTaskId: this.visitTaskId,
questionId: questionId,
rowId: rowId
}
await splitLesion(params)
await this.getReadingQuestionAndAnswer()
this.$nextTick(() => {
this.tableQuestions.forEach(item => {
@ -521,7 +528,11 @@ export default {
})
})
})
})
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
isCanActiveTool(toolName) {
this.getUnSaveTarget()
@ -942,6 +953,39 @@ export default {
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()
@ -1015,11 +1059,28 @@ export default {
</script>
<style lang="scss" scoped>
.measurement-wrapper{
height: 100%;
overflow-y: auto;
// overflow: hidden;
.container{
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{
padding: 5px;

View File

@ -110,34 +110,38 @@
/>
</template>
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask">
<!-- 首次分裂的病灶只能选择存在 -->
<template v-if="answers.IsFristAdd=== 'True' && answers.SplitOrMergeType === '0'">
<el-option
v-for="item of $d[qs.DictionaryCode]"
v-show="item.value === 0"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<!-- 首次添加的新病灶不能为无法评估和消失 -->
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
<el-option
v-for="item of $d[qs.DictionaryCode]"
v-show="item.value === 0 || item.value === 1"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<template v-else>
<el-option
v-for="item of filterState($d[qs.DictionaryCode])"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<el-option-group
:label="!isNaN(parseFloat(answers.LastTaskState)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(qs.DictionaryCode,parseFloat(answers.LastTaskState))}` : ''"
>
<!-- 首次分裂的病灶只能选择存在 -->
<template v-if="answers.IsFristAdd=== 'True' && answers.SplitOrMergeType === '0'">
<el-option
v-for="item of $d[qs.DictionaryCode]"
v-show="item.value === 0"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<!-- 首次添加的新病灶不能为无法评估和消失 -->
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
<el-option
v-for="item of $d[qs.DictionaryCode]"
v-show="item.value === 0 || item.value === 1"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<template v-else>
<el-option
v-for="item of filterState($d[qs.DictionaryCode])"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
</el-option-group>
</template>
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
<el-option
@ -340,16 +344,15 @@ export default {
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)
this.$set(this.questionForm, stateId, 0)
var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : ''
const lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : ''
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : ''
const lesionLength = this.getQuestionVal(0)
const lesionShort = this.getQuestionVal(1)
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.isRender = true
@ -515,8 +518,8 @@ export default {
}
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : ''
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : ''
const lesionLength = this.getQuestionVal(0)
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 })
if (question.QuestionMark === 7) {
@ -575,9 +578,8 @@ export default {
}
var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null
var lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : ''
var lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : ''
var lesionLength = this.getQuestionVal(0)
var lesionShort = this.getQuestionVal(1)
//
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 = ''
if (lesionState) {
if (this.lesionType === 0 && lesionState === 1) {
@ -646,8 +648,8 @@ export default {
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionL = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : ''
var lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : ''
const lesionL = this.getQuestionVal(0)
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.toolType = measureData.type
DicomEvent.$emit('refreshStudyListMeasureData')
@ -670,27 +672,31 @@ export default {
}
},
getQuestionVal(questionMark) {
var idx = this.questions.findIndex(i => i.QuestionMark === questionMark)
const idx = this.questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) {
var questionId = this.questions[idx].Id
return this.questionForm[questionId]
const questionId = this.questions[idx].Id
const answer = this.questionForm[questionId]
if (isNaN(parseFloat(answer))) {
return answer
} else {
return parseFloat(answer)
}
} else {
return ''
}
},
filterState(arr) {
if (!this.isBaseLineTask) {
var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : 0
const lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : 0
const lastLesionL = !isNaN(parseInt(this.answers.LastTaskMajorAxis)) ? parseInt(this.answers.LastTaskMajorAxis) : 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 === 'Length' || this.questionForm.MeasureData.type === 'Bidirectional') && lesionShort < lastLesionS) {
const isLymphLesion = this.getQuestionVal(2)
const lesionLength = this.getQuestionVal(0)
const lesionShort = this.getQuestionVal(1)
const bLesionL = !isNaN(parseInt(this.answers.LastTaskMajorAxis)) ? parseInt(this.answers.LastTaskMajorAxis) : 0
const bLesionS = !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) {
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)
} 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)
}
return arr
@ -754,227 +760,228 @@ export default {
// Blob
return new Blob([bytesCode], { type: imgtype })
},
handleSave() {
this.$refs.measurementForm.validate(async valid => {
if (!valid) return
const loading = this.$loading({ fullscreen: true })
var measureData = this.questionForm.MeasureData
var lesionState = this.getQuestionVal(7)
var lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : ''
async handleSave() {
const valid = await this.$refs.measurementForm.validate()
if (!valid) return
const loading = this.$loading({ fullscreen: true })
var measureData = this.questionForm.MeasureData
var lesionState = this.getQuestionVal(7)
var lesionLength = this.getQuestionVal(0)
if (this.isBaseLineTask) {
// 线
// 0
if (this.lesionType === 0 && lesionState === 0) {
// 10mm2
if (!(measureData && measureData.type === 'Length' && lesionLength >= 10 && (measureData.thick && lesionLength >= 2 * measureData.thick || !measureData.thick))) {
// 10mm2使
this.$confirm(this.$t('trials:readingBM:warnning:msg06'), {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
loading.close()
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
}
if (this.isBaseLineTask) {
// 线
// 0
if (this.lesionType === 0 && lesionState === 0) {
// 10mm2
if (!(measureData && measureData.type === 'Length' && lesionLength >= 10 && (measureData.thick && lesionLength >= 2 * measureData.thick || !measureData.thick))) {
// 10mm2使
this.$confirm(this.$t('trials:readingBM:warnning:msg06'), {
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 = ''
if (val && measureData && this.questionForm.IsDicomReading) {
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 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)
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.currentMarkTool = measureData ? measureData.type : ''
@ -1018,94 +1026,87 @@ export default {
this.$set(this.questionForm, 'saveTypeEnum', 2)
this.originalQuestionForm = { ...this.questionForm }
loading.close()
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 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('close')
DicomEvent.$emit('getReportInfo', true)
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'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(async() => {
//
var lengId = this.getQuestionId(0)
this.$set(this.questionForm, lengId, '')
const confirm = await this.$confirm(
this.$t('trials:reading:warnning:msg47'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
//
var lengId = this.getQuestionId(0)
this.$set(this.questionForm, lengId, '')
var stateId = this.getQuestionId(7)
this.$set(this.questionForm, stateId, '')
// saveTypeEnum 01访/
if (this.questionForm.RowId) {
this.$set(this.questionForm, 'saveTypeEnum', 1)
} else {
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 })
DicomEvent.$emit('getMeasureData')
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionLength = ''
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : ''
var stateId = this.getQuestionId(7)
this.$set(this.questionForm, stateId, '')
// saveTypeEnum 01访/
if (this.questionForm.RowId) {
this.$set(this.questionForm, 'saveTypeEnum', 1)
} else {
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 })
DicomEvent.$emit('getMeasureData')
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionLength = ''
const lesionState = this.getQuestionVal(7)
if (!this.questionForm.IsDicomReading) {
DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData)
}
this.$set(this.questionForm, 'IsDicomReading', true)
if (!this.questionForm.IsDicomReading) {
DicomEvent.$emit('removeNoneDicomMeasureData', this.questionForm.MeasureData)
}
this.$set(this.questionForm, 'IsDicomReading', true)
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', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: anwsers })
DicomEvent.$emit('refreshStudyListMeasureData')
})
.catch(() => {})
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', { isLymphLesion: 0, lesionPart, lesionOrgan, lesionState, saveTypeEnum: this.questionForm.saveTypeEnum, lesionLength, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: anwsers })
DicomEvent.$emit('refreshStudyListMeasureData')
},
handleDelete() {
async 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.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('getReportInfo', true)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
loading.close()
}
}).catch(() => { loading.close() })
} else {
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.IsDicomReading && this.questionForm.MeasureData) {
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)
}
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) {
// ''
this.$confirm(this.$t('trials:reading:warnning:msg49'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(async() => {
//
if (this.questionForm.MeasureData) {
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex })
}
DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
})
.catch(() => {})
const confirm = await this.$confirm(
this.$t('trials:reading:warnning:msg49'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
if (this.questionForm.MeasureData) {
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.questionForm.MeasureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex })
}
DicomEvent.$emit('getMeasureData')
this.$emit('close', { lesionType: this.lesionType, rowIndex: this.rowIndex, visitTaskId: this.visitTaskId })
} else {
// saveTypeEnum 01访/
@ -1150,13 +1166,12 @@ export default {
if (isNaN(parseInt(lesionState)) && this.answers.IsFristAdd === 'False') {
const stateId = this.getQuestionId(7)
this.$set(this.questionForm, stateId, 2)
var isLymphLesion = this.getQuestionVal(2)
isLymphLesion = !isNaN(parseInt(isLymphLesion)) ? parseInt(isLymphLesion) : null
const isLymphLesion = this.getQuestionVal(2)
const lesionPart = this.getQuestionVal(8)
const lesionOrgan = this.getQuestionVal(6)
const lesionLength = !isNaN(parseInt(this.getQuestionVal(0))) ? this.getQuestionVal(0) : ''
const lesionShort = !isNaN(parseInt(this.getQuestionVal(1))) ? this.getQuestionVal(1) : ''
const lesionState = !isNaN(parseInt(this.getQuestionVal(7))) ? parseInt(this.getQuestionVal(7)) : ''
const lesionLength = this.getQuestionVal(0)
const lesionShort = this.getQuestionVal(1)
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 })
}
}

View File

@ -1,11 +1,21 @@
<template>
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
<div class="measurement-wrapper">
<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="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="lesions">
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" />
@ -118,6 +128,7 @@
</template>
<script>
import { splitLesion } from '@/api/trials'
import { resetReadingTask } from '@/api/reading'
import DicomEvent from './../DicomEvent'
import store from '@/store'
@ -154,7 +165,6 @@ export default {
},
data() {
return {
height: window.innerHeight - 140,
questions: [],
activeName: '',
activeItem: {
@ -197,7 +207,8 @@ export default {
}
},
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)
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
DicomEvent.$on('setCollapseActive', measureData => {
@ -217,8 +228,6 @@ export default {
DicomEvent.$on('split', measureData => {
this.handleSplit(measureData.RowId, measureData.QuestionId)
})
window.addEventListener('resize', this.setHeight)
},
beforeDestroy() {
DicomEvent.$off('loadMeasurementList')
@ -397,9 +406,6 @@ export default {
} catch (e) { console.log(e) }
})
},
setHeight() {
this.height = window.innerHeight - 140
},
getQuestionAnswer(questions, questionMark, answers) {
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
if (idx > -1) {
@ -497,15 +503,15 @@ export default {
}
}
},
split(rowId, questionId) {
async split(rowId, questionId) {
const loading = this.$loading({ fullscreen: true })
var params = {
visitTaskId: this.visitTaskId,
questionId: questionId,
rowId: rowId
}
splitLesion(params).then(async res => {
loading.close()
try {
var params = {
visitTaskId: this.visitTaskId,
questionId: questionId,
rowId: rowId
}
await splitLesion(params)
await this.getReadingQuestionAndAnswer()
this.$nextTick(() => {
this.tableQuestions.forEach(item => {
@ -515,7 +521,11 @@ export default {
})
})
})
})
loading.close()
} catch (e) {
loading.close()
console.log(e)
}
},
isCanActiveTool(toolName) {
this.getUnSaveTarget()
@ -879,6 +889,39 @@ export default {
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()
@ -945,11 +988,28 @@ export default {
</script>
<style lang="scss" scoped>
.measurement-wrapper{
height: 100%;
overflow-y: auto;
// overflow: hidden;
.container{
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{
padding: 5px;

View File

@ -12,8 +12,15 @@
style="margin-right:5px;"
@change="handleShowDetail"
/>
<!--评估报告-->
<el-button :loading="reportBtnLoading" v-if="readingTaskState>=2" type="primary" size="small" @click="showReport">{{$t('trials:dicoms:button:evaluationReport')}}</el-button>
<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"
@ -24,7 +31,7 @@
{{ $t('trials:readingReport:button:refresh') }}
</el-button>
<el-button
v-if="readingTaskState<2"
v-if="readingTaskState<2 && CriterionType !== 10"
type="primary"
size="small"
@click="handleSave(true)"
@ -95,8 +102,8 @@
</div>
</template>
<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'}">
<template v-if="task.VisitTaskId === visitTaskId && readingTaskState < 2 && [13,14,15,21,22,42].includes(scope.row.QuestionType)">
<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,42].includes(scope.row.QuestionType)">
<!-- 是否存在疾病基线时可修改 -->
<template v-if="task.IsBaseLine && scope.row.QuestionType=== 15">
<el-select
@ -150,32 +157,6 @@
</template>
</el-select>
</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">
{{ $fd(scope.row.DictionaryCode, currentEvaluateResult) }}
</template> -->
@ -200,8 +181,9 @@
@change="evaluateReasonChange"
/>
<!-- 系统评估结果为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-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-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>
</template>
<!-- <template v-else>
<span>{{ currentTaskReason }}</span>
@ -284,15 +266,11 @@
</div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog>
<!--评估报告-->
<PreviewFileDialog
:visible.sync="previewFileVisible"
:fileData="fileData"
/>
</div>
</template>
<script>
import { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getTaskAdditionalQuestion } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import DicomEvent from './DicomEvent'
import const_ from '@/const/sign-code'
@ -302,11 +280,9 @@ import store from '@/store'
import { mapGetters } from 'vuex'
import { changeURLStatic } from '@/utils/history.js'
import AdditionalAssessment from './AdditionalAssessment'
import { showReadReport } from "@/api/export";
import PreviewFileDialog from "@/components/PreviewFileDialog/PreviewFileDialog.vue";
export default {
name: 'ReportPage',
components: { SignForm, AdditionalAssessment,PreviewFileDialog },
components: { SignForm, AdditionalAssessment },
props: {
visitTaskId: {
type: String,
@ -343,13 +319,7 @@ export default {
assessmentQuestions: [],
tLesionCount: null,
ntLesionCount: null,
openWindow: null,
//
previewFileVisible: false,
fileData: {},
reportBtnLoading:false,
intervalDays: null
openWindow: null
}
},
computed: {
@ -390,35 +360,6 @@ export default {
}
},
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) {
return new Promise(resolve => {
this.$confirm(msg, {
@ -470,32 +411,38 @@ export default {
getTableHeight() {
this.height = window.innerHeight - 170
},
getReportInfo(IsCalculate) {
async getReportInfo(IsCalculate) {
this.loading = true
var params = {
visitTaskId: this.visitTaskId,
trialId: this.$router.currentRoute.query.trialId,
IsCalculate: IsCalculate !== false
}
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()
this.visitTaskList = res.Result.VisitTaskList
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
this.taskQuestions = []
taskQuestions.forEach(item => {
this.$set(this.taskQuestions, this.taskQuestions.length, item)
})
const tLesion = res.Result.LesionCountList.find(i => i.LesionType === 0)
this.tLesionCount = tLesion ? tLesion.Count : 0
const ntLesion = res.Result.LesionCountList.find(i => i.LesionType === 1)
this.ntLesionCount = ntLesion ? ntLesion.Count : 0
this.setScrollTop()
try {
var params = {
visitTaskId: this.visitTaskId,
trialId: this.$router.currentRoute.query.trialId,
IsCalculate: IsCalculate !== false
}
const res = await getReadingReportEvaluation(params)
if (res.IsSuccess) {
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()
this.visitTaskList = res.Result.VisitTaskList
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
this.taskQuestions = []
taskQuestions.forEach(item => {
this.$set(this.taskQuestions, this.taskQuestions.length, item)
})
const tLesion = res.Result.LesionCountList.find(i => i.LesionType === 0)
this.tLesionCount = tLesion ? tLesion.Count : 0
const ntLesion = res.Result.LesionCountList.find(i => i.LesionType === 1)
this.ntLesionCount = ntLesion ? ntLesion.Count : 0
this.setScrollTop()
}
this.loading = false
}).catch(() => { this.loading = false })
} catch (e) {
this.loading = false
console.log(e)
}
},
setScrollTop(a) {
setTimeout(() => {
@ -503,7 +450,6 @@ export default {
if (this.$refs.reportList) {
this.getTableHeight()
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
}
})
}, 50)
@ -611,7 +557,7 @@ export default {
this.currentExistDisease = obj.Answers[this.visitTaskId]
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.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.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) {
obj.Childrens = this.getQuestions(item.Childrens, isNTFilterLength, lesionType, isLymphNodes)
}
@ -657,7 +599,7 @@ export default {
}
this.currentTaskReason = ''
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) {
this.answerArr[idx].answer = val
}
@ -670,39 +612,32 @@ export default {
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() {
await this.handleSave(false)
await this.verifyVisitTaskQuestions()
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
var isBaseline = this.visitTaskList[i].IsBaseLine
if (isBaseline) {
this.assessmentQuestions = await this.getAdditionalAssessments()
if (this.assessmentQuestions.length > 0) {
this.loading = true
try {
await this.handleSave(false)
await verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId })
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
var isBaseline = this.visitTaskList[i].IsBaseLine
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 {
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}
} else {
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
this.loading = false
} catch (e) {
this.loading = false
}
},
sign() {
@ -713,31 +648,6 @@ export default {
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() {
this.$nextTick(() => {
this.$refs.reportList && this.$refs.reportList.doLayout()
@ -752,15 +662,16 @@ export default {
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
submitDicomVisitTask(params).then(async res => {
try {
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
const res = await submitDicomVisitTask(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) {
@ -776,7 +687,8 @@ export default {
await store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
// DicomEvent.$emit('setReadingState', 2)
await store.dispatch('reading/setCurrentReadingTaskState', 2)
var isAutoTask = await this.getAutoTaskVal()
const res = await getAutoCutNextTask()
var isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
// DicomEvent.$emit('reload')
// DicomEvent.$emit('getNextTask')
@ -800,19 +712,12 @@ export default {
// DicomEvent.$emit('readingPageStateUpdate', { readingTaskState: 2 })
}
this.loading = false
}).catch(() => {
} catch (e) {
this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false
}
})
},
getAutoTaskVal() {
return new Promise((resolve, reject) => {
getAutoCutNextTask().then(res => {
resolve(res.Result.AutoCutNextTask)
}).catch(() => { reject() })
})
}
},
previewDicoms(task) {
if (this.openWindow) {
@ -820,7 +725,8 @@ export default {
}
var token = getToken()
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 trialId = this.$router.currentRoute.query.trialId
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
@ -831,14 +737,14 @@ export default {
this.openWindow = window.open(routeData.href, '_blank')
},
handleSave(isPrompt) {
return new Promise((resolve, reject) => {
return new Promise(async(resolve, reject) => {
var isBeill
var evaluateResult = ''
var evaluateAjustReason = ''
this.answers = []
var isExistEvaluateResult = false
this.answerArr.map(item => {
if (item.questionType === 13 || item.questionType === 42 || item.questionType === 21) {
if (item.questionType === 13 || item.questionType === 42) {
evaluateResult = item.answer
isExistEvaluateResult = true
}
@ -870,7 +776,7 @@ export default {
reject()
return
}
if (this.tumorEvaluate !== null && isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) {
if (isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) {
//
this.$confirm(this.$t('trials:readingReport:message:msg3'), {
type: 'warning',
@ -881,21 +787,57 @@ export default {
return
}
this.loading = true
var params = {
visitTaskId: this.visitTaskId,
answers: this.answers
}
changeDicomReadingQuestionAnswer(params).then(res => {
if (isPrompt) {
try {
var params = {
visitTaskId: this.visitTaskId,
answers: this.answers
}
const res = await changeDicomReadingQuestionAnswer(params)
if (res.IsSuccess && isPrompt) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
this.loading = false
resolve()
}).catch(() => {
} catch (e) {
this.loading = false
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{
color: #428bca;
}
.colorOfRed{
color: #f66;
}
</style>

View File

@ -49,20 +49,42 @@
/>
<div class="image-desc">
<div class="flex-div">
<div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }} </div>
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount && series.modality!== 'SR'">
<!-- 下载 -->
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<div style="width: 40px;display: flex;flex-direction: row;justify-content: space-between;">
<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">
<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)" />
</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>
<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)" />
</el-tooltip>
<div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<el-popover
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>
<p v-show="series.description">
<el-tooltip class="item" effect="dark" :content="series.description" placement="right">
@ -73,7 +95,10 @@
<p v-show="series.sliceThickness && !study.IsCriticalSequence">
T: {{ parseFloat(series.sliceThickness).toFixed(digitPlaces) }}
</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
</p>
@ -88,9 +113,9 @@
</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
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))"
:percentage="parseInt((series.prefetchInstanceCount / series.instanceCount).toFixed(2))"
/>
</div>
@ -125,18 +150,13 @@
</div>
</template>
<script>
import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
// import * as cornerstone from 'cornerstone-core'
import requestPoolManager from '@/utils/request-pool'
import DicomEvent from './DicomEvent'
import { mapGetters } from 'vuex'
import store from '@/store'
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 {
name: 'StudyList',
components: { SrList },
@ -219,7 +239,8 @@ export default {
// }
},
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'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
DicomEvent.$on('refreshStudyListMeasureData', () => {
@ -233,99 +254,72 @@ export default {
// 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('cornerstoneimagecachechanged', this.cornerstoneimagecachechanged)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
})
// window.addEventListener('beforeunload', e => {
// cornerstone.imageCache.purgeCache()
// })
},
beforeDestroy() {
cornerstone.imageCache.purgeCache()
// cornerstone.imageCache.purgeCache()
DicomEvent.$off('refreshStudyListMeasureData')
window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() })
// window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() })
},
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() {
const loading = this.$loading({ fullscreen: true })
//
this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer()
res.map((item) => {
this.loadInitialImage(item)
res.map(async(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) {
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
var priority = parseInt(new Date().getTime())
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.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 })
})
}
if (res[i].isExistMutiFrames) {
res[i].instanceInfoList.map(image => {
priority--
this.imageList.push({ imageId: image.ImageId, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].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()
}
}
@ -341,9 +335,9 @@ export default {
var p = parseInt(new Date().getTime())
var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex]
requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100).then(res => {
if (seriesInfo.isCurrentTask) {
this.imageLoaded({ studyIndex: seriesInfo.studyIndex, seriesIndex: seriesInfo.seriesIndex, imageId: res.imageId }, res.data.string('x0020000e'))
}
// if (seriesInfo.isCurrentTask) {
// this.imageLoaded({ studyIndex: seriesInfo.studyIndex, seriesIndex: seriesInfo.seriesIndex, imageId: res.imageId }, res.data.string('x0020000e'))
// }
})
},
getStudyList() {
@ -355,11 +349,31 @@ export default {
this.studyList = this.visitTaskList[idx].StudyList
var sIdx = this.studyList.findIndex(s => s.IsDicom)
if (sIdx > -1) {
this.studyIndex = sIdx
this.seriesIndex = 0
console.log(this.studyIndex, this.studyIndex)
// this.studyIndex = sIdx
// c = 0
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
@ -368,11 +382,26 @@ export default {
async getInitSeries() {
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)
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])
if (Object.keys(obj).length !== 0) {
this.studyIndex = obj.studyIndex
@ -381,9 +410,13 @@ export default {
this.activeNames = [`${this.studyList[ this.studyIndex].StudyId}`]
this.studyList[ obj.studyIndex].SeriesList[obj.seriesIndex].isFirstRender = true
} else {
//
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 })
@ -407,6 +440,7 @@ export default {
const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList])
seriesList.push(firstObj.series)
const secondObj = this.getSecondMarkedSeries(firstObj, { ...this.visitTaskList[idx] })
this.studyIndex = secondObj.studyIndex
this.seriesIndex = secondObj.seriesIndex
@ -441,9 +475,10 @@ export default {
const sdIndx = studyList.findIndex(sd => sd.StudyId === measureDatas[i].StudyId)
const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId)
// const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId))
// const instanceList = seriesList[srIdx].instanceList
const imageIds = seriesList[srIdx].imageIds
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]
series.imageIdIndex = isIdx
@ -514,8 +549,9 @@ export default {
const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId)
// const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId))
const imageIds = seriesList[srIdx].imageIds
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]
series.imageIdIndex = isIdx
@ -544,22 +580,20 @@ export default {
obj.series = seriesObj.series
obj.seriesId = seriesObj.series.seriesId
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
},
strSimilarity2Number(s, t) {
@ -613,7 +647,10 @@ export default {
this.studyIndex = studyIndex
this.seriesIndex = seriesIndex
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)
if (!series.loadStatus && series.modality !== 'SR') {
this.loopLoadStatus = -1
@ -626,9 +663,15 @@ export default {
}
if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime())
series.imageIds.map((imageId) => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
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()
@ -647,6 +690,59 @@ export default {
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) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx === -1) return
@ -656,7 +752,8 @@ export default {
var activeNames = `${this.studyList[obj.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx])
// console.log('setSeriesActive', obj)
this.loadImages(obj)
},
selectSeries(obj) {
var seriseList = this.studyList.map(s => s.SeriesList).flat()
@ -681,10 +778,27 @@ export default {
var activeNames = `${this.studyList[series.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx])
this.loadImages(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 isCurrentTask = taskInfo.IsCurrentTask
// var priority = isCurrentTask ? parseInt(new Date().getTime()) : 999
@ -705,10 +819,17 @@ export default {
// }
//
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 })
})
if (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
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) {
// requestPoolManager.startTaskTimer()
this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
if (res) {
this.imageLoaded(image, res.data.string('x0020000e'))
}
})
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
})
requestPoolManager.sortTaskPool()
@ -744,12 +861,22 @@ export default {
}
if (!isAddToTakPool) {
const priority = parseInt(new Date().getTime())
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 (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
const index = this.cachedImages.findIndex(item => item.uri === image)
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) {
this.loopLoadStatus = 0
this.loopLoad()
@ -763,83 +890,6 @@ export default {
console.log('stopLoadSeries')
requestPoolManager.removeTask(series.seriesId)
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;
margin: 0px;
}
}
}
/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>

View File

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

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

View File

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

View File

@ -2,22 +2,37 @@
<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;">
<h3 style="color: #ddd;padding: 5px 0px;margin: 0;" v-if="isReadingShowSubjectInfo">
<span v-if="subjectCode">{{ subjectCode }} </span>
<span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
<div class="basic-info">
<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>
<h3 v-if="isReadingShowSubjectInfo">
<span v-if="subjectCode">{{ subjectCode }} </span>
<span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3>
</div>
<QuestionsPreview
ref="QuestionsPreview"
v-if="ecrfShow"
v-if="ecrfShow && TrialReadingCriterionId"
:visitTaskId="visitTaskId"
:criterionId="TrialReadingCriterionId">
</QuestionsPreview>
</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">
<el-button size="mini" v-if="readingTaskState<2" style="margin-right: 10px" @click="handleSave(true)">
<div class="questions-footer">
<!-- <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')}}
</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>
</div>
<!-- 签名框 -->
@ -77,7 +92,8 @@
</template>
<script>
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 SignForm from '@/views/trials/components/newSignForm'
import QuestionsPreview from './CustomizeQuestionsPreview'
@ -144,7 +160,8 @@ export default {
}
},
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.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
DicomEvent.$on('getCustomTableQuestionAnswer', (visitTaskId) => {
@ -168,7 +185,6 @@ export default {
methods: {
async initList(){
if (this.visitTaskId !== this.lastCanvasTaskId) {
this.activeName = ''
this.ecrfShow = true
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId)
console.log(i)
@ -216,19 +232,26 @@ export default {
this.measureData = measureData
},
modifyMeasuredData(measureData) {
console.log(measureData)
measureData.visitTaskId = this.visitTaskId
measureData.measureData.pictureBaseStr = ''
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
submitCustomTag(params).then(() => {
if (this.readingTaskState >=2) {
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) {
console.log('measureData', measureData)
@ -237,24 +260,47 @@ export default {
},
handleMeasuredDataCancel() {
this.measuredDataVisible = false
// DicomEvent.$emit('updateImage')
},
handleMeasuredDataSave() {
this.$refs.measuredDataForm.validate(valid => {
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.pictureBaseStr = ''
let params = JSON.parse(JSON.stringify(this.measureData))
params.measureData = JSON.stringify(this.measureData)
submitCustomTag(params).then(async (res) => {
this.measuredDataVisible = false
this.form.measuredDataName = ''
this.measureData.Id = res.Result
await store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, ...this.measureData })
await store.dispatch('reading/getCustomizeMeasuredData', this.visitTaskId)
DicomEvent.$emit('updateImage')
})
if (this.readingTaskState >=2) {
this.measuredDataVisible = false
this.form.measuredDataName = ''
store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.measureData })
DicomEvent.$emit('updateImage')
this.$message.success(this.$t('common:message:savedSuccessfully'))
} else {
let params = JSON.parse(JSON.stringify(this.measureData))
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) {
if (isSign) {
@ -291,7 +337,7 @@ export default {
distinguishCancelAndClose: true
})
.then(() => {
try {DicomEvent.$emit('getNextTask')} catch (e) {console.log(e)}
window.location.reload()
})
.catch(action => {
})
@ -325,9 +371,87 @@ export default {
if (this.visitTaskId !== obj.visitTaskId) {
this.visitTaskId = obj.visitTaskId
this.taskBlindName = obj.taskBlindName
this.activeName = ''
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{
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{
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>

View File

@ -7,7 +7,7 @@
{{ question.GroupName }}
</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;"
>
<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">
<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 v-else-if="item.Type === 'number'">
{{scope.row[item.Id] ? parseFloat(scope.row[item.Id]).toFixed(digitPlaces) : null}}
@ -67,7 +67,7 @@
:label="`${question.QuestionName}`"
:prop="question.Id"
: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']},
]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
@ -120,9 +120,9 @@
<template v-else>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
:key="val.trim()"
:label="val.trim()"
:value="val.trim()"
/>
</template>
@ -135,10 +135,10 @@
>
<el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:key="val.trim()"
:label="val.trim()"
>
{{ val }}
{{ val.trim() }}
</el-radio>
</el-radio-group>
<!-- 复选框 -->
@ -149,16 +149,50 @@
<el-checkbox
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:label="val.trim()"
>
{{ val }}
{{ val.trim() }}
</el-checkbox>
</el-checkbox-group>
<!-- 自动分类 -->
<el-input
v-if="question.Type === 'class'"
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
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" -->
@ -176,12 +210,24 @@
/>
<!-- 数值 -->
<!-- :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
type="number"
v-if="question.Type === 'number' && question.DataSource !== 1"
@change="((val)=>{formItemNumberChange(val, question)})"
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')));console.log(localStorage.getItem('digitPlaces'))"
@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]"
>
@ -191,7 +237,7 @@
<el-input
type="number"
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)"
:disabled="question.DataSource === 1"
v-model="questionForm[question.Id]"
@ -202,59 +248,37 @@
<!-- 上传图像 -->
<el-upload
v-if="question.Type==='upload'"
:action="question.FileType"
:limit="question.ImageCount"
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="(file) => {return handleBeforeUpload(file, question.FileType)}"
:http-request="uploadScreenshot"
:on-remove="handleRemove"
: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">
{{this.$t('common:button:upload')}}
</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-dialog
v-if="question.Type==='upload'"
append-to-body
:visible.sync="imgVisible"
width="600px"
<viewer
v-if="question.Type==='upload' && imgVisible"
:ref="imageUrl"
style="margin:0 10px;"
:images="[imageUrl]"
>
<el-image :src="imageUrl" width="100%">
<div slot="placeholder" class="image-slot">
加载中<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
<img
v-show="false"
crossorigin="anonymous"
:src="imageUrl"
alt="Image"
>
</viewer>
</el-form-item>
</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
v-for="(item) in question.Childrens"
:key="item.Id"
@ -295,9 +319,8 @@
:type="addOrEdit.type"
:CalculationList="CalculationTabelList"
@formItemTableNumberChange="formItemTableNumberChange"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
@setFormTableItemData="setFormTableItemData"
@resetFormItemData="resetTableFormItemData"
@setFormItemData="setFormTableItemData"
/>
</el-form>
</template>
@ -374,7 +397,8 @@ export default {
RowIndex: 0,
RowId: null,
digitPlaces: 0,
CalculationTabelList: []
CalculationTabelList: [],
classArr: []
}
},
watch: {
@ -382,9 +406,18 @@ export default {
deep: true,
immediate: true,
handler(v, oldv) {
// try {
// if (!v[this.question.Id] || !oldv[this.question.Id]) return
// } catch (e) {
// }
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) {
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)
}
@ -392,21 +425,21 @@ export default {
},
mounted() {
this.digitPlaces = localStorage.getItem('digitPlaces') ? parseInt(localStorage.getItem('digitPlaces')) : 0
if (this.question.Type === 'class') {
this.ClassifyAlgorithmsList = JSON.parse(this.question.ClassifyAlgorithms)
}
setInterval(()=> {
if (this.question.Type === 'class') {
let o = this.ClassifyAlgorithmsList.find(v => {
return this.questionForm[this.question.ClassifyQuestionId] >= v.gt && this.questionForm[this.question.ClassifyQuestionId] < v.lt
})
if (this.questionForm[this.question.ClassifyQuestionId]) {
this.questionForm[this.question.Id] = o ? o.label : null
} else {
this.questionForm[this.question.Id] = null
}
}
}, 300)
// if (this.question.Type === 'class') {
// this.ClassifyAlgorithmsList = JSON.parse(this.question.ClassifyAlgorithms)
// }
// setInterval(()=> {
// if (this.question.Type === 'class') {
// let o = this.ClassifyAlgorithmsList.find(v => {
// return this.questionForm[this.question.ClassifyQuestionId] >= v.gt && this.questionForm[this.question.ClassifyQuestionId] < v.lt
// })
// if (this.questionForm[this.question.ClassifyQuestionId]) {
// this.questionForm[this.question.Id] = o ? o.label : null
// } else {
// this.questionForm[this.question.Id] = null
// }
// }
// }, 300)
if (this.question.Type === 'upload') {
if (this.questionForm[this.question.Id]) {
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()
if (this.questionForm[this.question.Id]) {
this.QuestionsForm = {}
@ -436,11 +469,9 @@ export default {
if (value.split('.')[1].length >= this.digitPlaces) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
}
} else {
}
},
deleteTableCol(row, index) {
console.log(row)
this.$confirm(this.$t('trials:uploadNonDicoms:message:msg1')).then(() => {
const loading = this.$loading({ fullscreen: true })
var param = {
@ -451,7 +482,7 @@ export default {
deleteReadingRowAnswer(param)
.then(async res => {
if (res.IsSuccess) {
this.$message.success('删除成功')
this.$message.success(this.$t('common:message:deletedSuccessfully'))
DicomEvent.$emit('reGetQuestionAnswer')
}
loading.close()
@ -461,11 +492,57 @@ export default {
})
},
setFormTableItemData(id, url) {
this.$set(this.QuestionsForm, id, url)
setFormTableItemData(obj) {
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() {
console.log(this.QuestionsForm)
this.$refs.tableQsForm.validate(valid => {
if (!valid) return
const loading = this.$loading({ fullscreen: true })
@ -474,7 +551,6 @@ export default {
for (const k in this.QuestionsForm) {
if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
console.log(this.QuestionsForm)
answers.push({ tableQuestionId: k, answer: this.QuestionsForm[k] })
}
}
@ -501,6 +577,7 @@ export default {
submitTableQuestion(params).then(async res => {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.QuestionsForm.RowId = res.Result.RowId
// DicomEvent.$emit('reGetQuestionAnswer')
this.save()
loading.close()
}).catch(() => { loading.close() })
@ -523,9 +600,7 @@ export default {
})
},
save() {
console.log(this.$refs.tableQsForm, this.QuestionsForm)
this.$refs['tableQsForm'].validate((valid) => {
console.log(valid)
if (!valid) return
if (this.addOrEdit.type === 'add') {
this.AnswersList.push(this.QuestionsForm)
@ -533,7 +608,7 @@ export default {
var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId)
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.addOrEdit.visible = false
})
@ -543,9 +618,10 @@ export default {
if (rules.CalculateQuestionList.length === 0) {
return false
}
let dataArr = []
rules.CalculateQuestionList.forEach((o, i) => {
if (i === 0) {
if (rules.CustomCalculateMark > 4) {
if (rules.CustomCalculateMark > 4 && rules.CustomCalculateMark < 10) {
switch (rules.CustomCalculateMark) {
case 5:
this.questionForm[o.QuestionId].forEach((q, qi) => {
@ -592,6 +668,9 @@ export default {
}
} else {
num = parseFloat(this.questionForm[o.TableQuestionId])
if (!isNaN(num)) {
dataArr.push(num)
}
}
} else {
switch (rules.CustomCalculateMark) {
@ -611,6 +690,38 @@ export default {
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;
}
}
})
@ -621,7 +732,12 @@ export default {
if (rules.ValueType === 2) {
num = num * 100
}
return num.toFixed(digitPlaces)
if (rules.CustomCalculateMark === 13 || rules.CustomCalculateMark === 14) {
return num
} else {
return num.toFixed(digitPlaces)
}
},
formItemNumberChange(questionId, isTable) {
if (isTable) {
@ -633,7 +749,7 @@ export default {
if (find) {
var num = this.logic(v)
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) {
var num = this.logic(v)
if (num !== false) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num })
this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
}
}
})
}
// 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() {
this.question.TableQuestions.Questions.forEach(v => {
if (v.Type === 'number' && v.DataSource === 1) {
var CalculateQuestions = JSON.parse(v.CalculateQuestions)
var num
this.question.TableQuestions.Questions.forEach((v) => {
if (v.Type === "number" && v.DataSource === 1) {
var CalculateQuestions = JSON.parse(v.CalculateQuestions);
var num,
arr = [];
CalculateQuestions.forEach((o, i) => {
if (i === 0) {
num = this.QuestionsForm[o.TableQuestionId]
num = parseFloat(this.QuestionsForm[o.TableQuestionId]);
arr = [num];
} else {
switch (v.CustomCalculateMark) {
case 1:
num += this.QuestionsForm[o.TableQuestionId]
num += parseFloat(this.QuestionsForm[o.TableQuestionId]);
break;
case 2:
num -= this.QuestionsForm[o.TableQuestionId]
num -= parseFloat(this.QuestionsForm[o.TableQuestionId]);
break;
case 3:
num *= this.QuestionsForm[o.TableQuestionId]
num *= parseFloat(this.QuestionsForm[o.TableQuestionId]);
break;
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;
}
}
})
this.$set(this.QuestionsForm, v.Id, num.toString())
});
this.$set(this.QuestionsForm, v.Id, num.toString());
}
})
});
},
openAddTableCol(row, index) {
this.addOrEdit.visible = true
this.addOrEdit.title = row.QuestionName + this.$t('trials:readingUnit:qsList:title:tableQs')
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
if (!index && index !== 0) {
this.addOrEdit.type = 'add'
this.QuestionsForm = {}
} else {
this.addOrEdit.type = 'edit'
console.log(this.questionForm)
this.QuestionsForm = Object.assign({}, this.questionForm[row.Id][index])
}
},
@ -709,7 +878,7 @@ export default {
})
},
formNumberItemChange(v) {
this.$emit('setFormItemData', { key: v.QuestionId, val: num })
this.$emit('setFormItemData', { key: v.QuestionId, val: num, question: v })
},
formItemChange(v, question) {
if (question.Childrens.length > 0) {
@ -724,8 +893,10 @@ export default {
// if (typeof val === 'boolean') {
// // 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) {
@ -741,9 +912,9 @@ export default {
},
setFormItemData(obj) {
this.$emit('setFormItemData', obj)
},
async uploadScreenshot(param) {
console.log('uploadScreenshot')
if (!this.visitTaskId) return
const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'),
@ -756,9 +927,8 @@ export default {
let file = await this.fileToBlob(param.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) })
console.log('fileList', this.fileList)
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()
// uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
// if (res.IsSuccess) {
@ -773,7 +943,6 @@ export default {
},
handleBeforeUpload(file, accept) {
//
console.log('handleBeforeUpload', file)
if (this.checkFileSuffix(file.name, accept) || accept === '-1') {
return true
} else {
@ -781,7 +950,6 @@ export default {
this.$alert(msg)
return false
}
console.log(file)
},
checkFileSuffix(fileName, accept) {
var index = fileName.lastIndexOf('.')
@ -794,17 +962,25 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
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.$nextTick(()=>{
this.$refs[this.imageUrl].$viewer.show()
})
}
},
//
handleRemove(file, fileList) {
console.log('handleRemove')
if (file && file.status === "success") {
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('|') : '' })
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
v-if="question.Type==='upload'"
:action="accept"
action
:accept="accept"
:limit="question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
@ -138,27 +139,41 @@
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
alt=""
<viewer
:ref="file.url"
:images="[imageUrl]"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
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>
<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
v-if="readingTaskState < 2"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete" />
</span>
</span>
</span>
</viewer>
</div>
</el-upload>
<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)
this.fileList.push({ name: param.file.name, url: 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()
},
handleBeforeUpload(file) {
@ -302,15 +317,21 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
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.$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('|') : '' })
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 }}
</el-checkbox>
</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" -->
<el-input
@ -136,39 +167,54 @@
<!-- 上传图像 -->
<el-upload
v-if="question.Type==='upload'"
:action="accept"
:limit="question.ImageCount"
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
:http-request="uploadScreenshot"
list-type="picture-card"
:on-remove="handleRemove"
: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" />
<div slot="file" slot-scope="{file}">
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
alt=""
<viewer
:ref="file.url"
:images="[imageUrl]"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
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>
<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
v-if="readingTaskState < 2"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete" />
</span>
</span>
</span>
</viewer>
</div>
</el-upload>
<el-dialog
@ -268,11 +314,11 @@ export default {
deep: true,
immediate: true,
handler(v, oldv) {
try {
if (!v[this.question.Id] || !oldv[this.question.Id]) return
} catch (e) {
}
this.formItemNumberChange(this.question.Id, false)
// try {
// if (!v[this.question.Id] || !oldv[this.question.Id]) return
// } catch (e) {
// }
// this.formItemNumberChange(this.question.Id, false)
}
},
},
@ -286,14 +332,15 @@ export default {
this.fileList.push({ name: '', url: `${url}` })
})
}
console.log('11')
}
if (this.type === 'edit') return
if (this.question.Type === 'number') {
console.log(this.questionForm)
this.$set(this.questionForm, this.question.Id, null)
} else {
this.$set(this.questionForm, this.question.Id, '')
}
// if (this.question.Type === 'number') {
// console.log(this.questionForm)
// this.$set(this.questionForm, this.question.Id, null)
// } else {
// this.$set(this.questionForm, this.question.Id, '')
// }
},
methods: {
save() {
@ -329,8 +376,10 @@ export default {
// if (typeof val === 'boolean') {
// // 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) {
@ -347,10 +396,11 @@ export default {
if (rules.CalculateQuestionList.length === 0) {
return false
}
let dataArr = []
var count = 0
var maxList = [], minList = []
rules.CalculateQuestionList.forEach((o, i) => {
if (rules.CustomCalculateMark > 4) {
if (rules.CustomCalculateMark > 4 && rules.CustomCalculateMark < 10) {
if (i !== 0) {
switch (rules.CustomCalculateMark) {
case 7:
@ -377,6 +427,7 @@ export default {
minList.push(this.questionForm[o.TableQuestionId])
count = parseFloat(this.questionForm[o.TableQuestionId])
num = parseFloat(this.questionForm[o.TableQuestionId])
dataArr.push(num)
}
} else {
if (i !== 0) {
@ -397,6 +448,26 @@ export default {
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;
}
} else {
num = parseFloat(this.questionForm[o.TableQuestionId])
@ -413,23 +484,7 @@ export default {
return num.toFixed(digitPlaces)
},
formItemNumberChange(v, question) {
console.log(this.CalculationList)
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) {
@ -462,7 +517,7 @@ export default {
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('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()
},
handleBeforeUpload(file) {
@ -471,14 +526,17 @@ export default {
// this.fileList = []
return true
} else {
this.$alert(`必须是 ${this.accept} 格式`)
let msg = this.$t(
"trials:readingUnit:qsList:message:imageFormat"
).replace("xxx", this.question.FileType)
this.$alert(msg)
return false
}
},
checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.')
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
} else {
return true
@ -486,15 +544,23 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
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('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,
activeName: 0,
CalculationList: [],
IsBaseline: true
IsBaseline: true,
classArr: []
}
},
mounted() {
@ -82,7 +83,7 @@ export default {
var answers = []
for (const k in this.questionForm) {
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 = {
@ -122,12 +123,15 @@ export default {
DicomEvent.$emit('setReadingState', res.OtherInfo.ReadingTaskState)
res.Result.SinglePage.map((v) => {
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)
}
if (v.Type === 'table') {
if (v.Type === 'table' || v.Type === 'basicTable') {
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') {
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
console.log(this.questions)
this.isRender = true
this.loading = false
})
@ -151,8 +154,8 @@ export default {
if (res.OtherInfo.FormType === 2) {
if (res.Result.MultiPage.length > 0) {
res.Result.MultiPage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0 && i.Type !== 'table') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Type !== 'table') {
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' && i.Type !== 'basicTable') {
this.$set(this.questionForm, v.Id, '')
}
if (v.Childrens.length > 0) {
@ -164,8 +167,8 @@ export default {
}
if (res.Result.PublicPage.length > 0) {
res.Result.PublicPage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0 && i.Type !== 'table') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && i.Type !== 'table') {
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' && i.Type !== 'basicTable') {
this.$set(this.questionForm, v.Id, '')
}
if (v.Childrens.length > 0) {
@ -176,11 +179,11 @@ export default {
}
} else {
res.Result.SinglePage.map((v) => {
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') {
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 !== 'basicTable' && v.Type !== 'number') {
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)
}
if (v.Type === 'number') {
@ -198,10 +201,10 @@ export default {
},
setChild(obj) {
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)
}
if (i.Type === 'table') {
if (i.Type === 'table' || i.Type === 'basicTable') {
i.TableQuestions.Questions.forEach(o => {
if (o.Type === 'number') {
i.TableQuestions.Answers.forEach((ite, index) => {
@ -211,6 +214,9 @@ export default {
})
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') {
this.$set(this.questionForm, i.Id, i.Answer === '' ? '' : parseFloat(i.Answer).toFixed(localStorage.getItem('digitPlaces')))
}
@ -224,6 +230,50 @@ export default {
},
setFormItemData(obj) {
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"
@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>
@ -71,7 +80,7 @@
</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 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>
<!-- 输入框 -->
<div>
@ -103,12 +112,12 @@
<el-option
v-for="val in scope.row.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
:label="val.trim()"
:value="val.trim()"
/>
</template>
</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]}}
</span>
<el-select
@ -121,14 +130,20 @@
<el-option
v-for="val in scope.row.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
:label="val.trim()"
:value="val.trim()"
/>
</template>
</el-select>
<span v-else-if="scope.row.Type==='select' || scope.row.Type==='radio'">
{{questionForm[scope.row.QuestionId]}}
</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
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]"
@ -260,6 +275,7 @@
</template>
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import DicomEvent from './../components/DicomEvent'
import CustomizeReportPageUpload from './CustomizeReportPageUpload'
import const_ from '@/const/sign-code'
@ -415,11 +431,11 @@ export default {
},
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') {
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 !== 'basicTable' && v.Type !== 'number') {
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)
this.$set(this.questionForm, v.QuestionId, tableAnswers)
// this.$set(v, 'xfIndex', i)
@ -435,17 +451,17 @@ export default {
},
setChild(obj) {
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])
}
if (i.Type === 'table') {
if (i.Type === 'table' || i.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
this.$set(this.questionForm, i.QuestionId, tableAnswers)
}
if (i.Type === 'number') {
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)
}
})
@ -775,13 +791,15 @@ export default {
},
previewDicoms(task) {
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 trialId = this.$router.currentRoute.query.trialId
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var criterionType = this.$router.currentRoute.query.criterionType
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 })
window.open(routeData.href, '_blank')
},
@ -826,6 +844,28 @@ export default {
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>
<div>
<el-upload
:action="accept"
:limit="question.ImageCount"
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : 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))}"
: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))"
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<img
class="el-upload-list__item-thumbnail"
crossOrigin="Anonymous"
:src="OSSclientConfig.basePath + file.url"
alt=""
<viewer
:ref="file.url"
:images="[imageUrl]"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
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>
<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>
<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>
<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>
</template>
@ -93,13 +96,13 @@ name: "CustomizeReportPageUpload",
this.urls.map(url => {
this.fileList.push({ name: '', url: `${url}` })
})
console.log(this.fileList)
// 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) {
if (this.question.FileType.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false
} else {
return true
@ -130,14 +133,25 @@ name: "CustomizeReportPageUpload",
// this.fileList = []
return true
} 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
}
},
//
handlePictureCardPreview(file) {
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
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) {

View File

@ -49,20 +49,52 @@
/>
<div class="image-desc">
<div class="flex-div">
<div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }} </div>
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount && series.modality!== 'SR'">
<!-- 下载 -->
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<div style="width: 40px;display: flex;flex-direction: row;justify-content: space-between;">
<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">
<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)" />
</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>
<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)" />
</el-tooltip>
<div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<el-popover
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>
<p v-show="series.description">
<el-tooltip class="item" effect="dark" :content="series.description" placement="right">
@ -73,10 +105,12 @@
<p v-show="series.sliceThickness && !study.IsCriticalSequence">
T: {{ parseFloat(series.sliceThickness).toFixed(digitPlaces) }}
</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
</p>
<div class="flex-div">
<div v-if="measureData && measureData.findIndex(v=>v.SeriesId === series.seriesId && v.MeasureData) > -1">
<!-- 有标注 -->
@ -88,9 +122,9 @@
</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
:percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))"
:percentage="parseInt((series.prefetchInstanceCount / series.instanceCount).toFixed(2))"
/>
</div>
@ -125,18 +159,11 @@
</div>
</template>
<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 DicomEvent from './../components/DicomEvent'
import { mapGetters } from 'vuex'
import store from '@/store'
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 {
name: 'StudyList',
components: { SrList },
@ -219,22 +246,23 @@ export default {
// }
},
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'))
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 => {
// var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
// if (idx > -1) {
// 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() {
cornerstone.imageCache.purgeCache()
},
methods: {
initStudyInfo() {
@ -242,81 +270,40 @@ export default {
//
this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer()
res.map((item) => {
this.loadInitialImage(item)
res.map(async(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) {
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
var priority = parseInt(new Date().getTime())
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.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 })
})
}
if (res[i].isExistMutiFrames) {
res[i].instanceInfoList.map(image => {
priority--
this.imageList.push({ imageId: image.ImageId, seriesId: res[i].seriesId, studyIndex: res[i].studyIndex, seriesIndex: res[i].seriesIndex, visitTaskId: res[i].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()
}
}
@ -331,14 +318,9 @@ export default {
loadInitialImage(seriesInfo) {
var p = parseInt(new Date().getTime())
var imageId = seriesInfo.imageIds[seriesInfo.imageIdIndex]
requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100).then(res => {
if (seriesInfo.isCurrentTask) {
this.imageLoaded({ studyIndex: seriesInfo.studyIndex, seriesIndex: seriesInfo.seriesIndex, imageId: res.imageId }, res.data.string('x0020000e'))
}
})
requestPoolManager.loadAndCacheImagePlus(imageId, seriesInfo.seriesId, p * 100)
},
getStudyList() {
console.log('getStudyList')
if (!this.isRender) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx > -1 && this.visitTaskList[idx].StudyList && this.visitTaskList[idx].StudyList.length > 0) {
@ -349,8 +331,27 @@ export default {
this.studyIndex = sIdx
this.seriesIndex = 0
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
@ -362,7 +363,22 @@ export default {
var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
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])
if (Object.keys(obj).length !== 0) {
@ -393,7 +409,7 @@ export default {
if (bsIdx > -1) {
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 })
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 seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[i].SeriesId)
// const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[i].InstanceId))
// const instanceList = seriesList[srIdx].instanceList
// 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]
series.imageIdIndex = isIdx
@ -504,9 +522,11 @@ export default {
if (sdIndx > -1) {
const seriesList = studyList[sdIndx].SeriesList
const srIdx = seriesList.findIndex(sr => sr.seriesId === measureDatas[mIdx].SeriesId)
// const instanceList = seriesList[srIdx].imageIds
const instanceList = seriesList[srIdx].instanceList
const isIdx = instanceList.findIndex(is => is.includes(measureDatas[mIdx].InstanceId))
// const instanceList = seriesList[srIdx].instanceList
// 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]
series.imageIdIndex = isIdx
@ -535,19 +555,18 @@ export default {
obj.series = seriesObj.series
obj.seriesId = seriesObj.series.seriesId
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
}
}
@ -604,7 +623,9 @@ export default {
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.imageIdIndex = 0
this.$emit('loadImageStack', dicomStatck)
if (!series.loadStatus && series.modality !== 'SR') {
this.loopLoadStatus = -1
@ -617,9 +638,15 @@ export default {
}
if (!isAddToTakPool) {
var priority = parseInt(new Date().getTime())
series.imageIds.map((imageId) => {
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
})
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()
@ -638,6 +665,58 @@ export default {
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) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
if (idx === -1) return
@ -647,7 +726,8 @@ export default {
var activeNames = `${this.studyList[obj.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx])
// this.loadImages(this.visitTaskList[idx])
this.loadImages(obj)
},
selectSeries(obj) {
var seriseList = this.studyList.map(s => s.SeriesList).flat()
@ -672,38 +752,25 @@ export default {
var activeNames = `${this.studyList[series.studyIndex].StudyId}`
if (this.activeNames.includes(activeNames)) return
this.activeNames.push(activeNames)
this.loadImages(this.visitTaskList[idx])
this.loadImages(series)
// this.loadImages(this.visitTaskList[idx])
store.dispatch('reading/setActiveSeries', series)
},
loadImages(taskInfo) {
// const isBaseLineTask = taskInfo.IsBaseLineTask
const isCurrentTask = taskInfo.IsCurrentTask
// var priority = isCurrentTask ? parseInt(new Date().getTime()) : 999
loadImages(series) {
var priority = parseInt(new Date().getTime())
this.studyList.map((study, studyIndex) => {
study.SeriesList.map((series, seriesIndex) => {
if (!series.loadStatus && series.isDicom && series.modality !== 'SR') {
// if (isCurrentTask || isBaseLineTask) {
// // /线
// series.imageIds.map(image => {
// this.imageList.push({ imageId: image, seriesId: series.seriesId, studyIndex: studyIndex, seriesIndex: seriesIndex, visitTaskId: series.visitTaskId, priority })
// })
// } else if (!isBaseLineTask && !isCurrentTask && study.IsCriticalSequence) {
// // 访
// 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 })
})
}
}
})
})
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()
},
@ -711,9 +778,7 @@ export default {
if (this.imageList.length > 0) {
// requestPoolManager.startTaskTimer()
this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
this.imageLoaded(image, res.data.string('x0020000e'))
})
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
})
requestPoolManager.sortTaskPool()
@ -733,12 +798,21 @@ export default {
}
if (!isAddToTakPool) {
const priority = parseInt(new Date().getTime())
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 (series.isExistMutiFrames) {
series.instanceInfoList.map(image => {
const index = this.cachedImages.findIndex(item => item.uri === image)
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) {
this.loopLoadStatus = 0
this.loopLoad()
@ -753,83 +827,6 @@ export default {
requestPoolManager.removeTask(series.seriesId)
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>
@ -977,3 +974,40 @@ 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>

View File

@ -57,10 +57,11 @@ export default {
this.getHotkeys()
},
methods: {
getHotkeys(isReset = false) {
async getHotkeys(isReset = false) {
this.loading = true
this.hotKeyList = []
getDoctorShortcutKey({ imageToolType: this.readingTool }).then(res => {
try{
let res = await getDoctorShortcutKey({ imageToolType: this.readingTool })
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 })
})
@ -68,11 +69,12 @@ export default {
this.$emit('reset', this.hotKeyList)
}
this.loading = false
}).catch(() => {
}catch(e){
this.loading = false
})
}
},
handleSave() {
async handleSave() {
this.loading = true
var params = {
imageToolType: this.readingTool,
@ -93,28 +95,34 @@ export default {
)
})
params.shortcutKeyList = shortcutKeyList
setShortcutKey(params).then(res => {
try {
await setShortcutKey(params)
this.$emit('reset', this.hotKeyList)
this.$emit('close')
this.loading = false
}).catch(() => {
}catch(e){
this.loading = false
})
}
},
handleReset() {
async handleReset() {
// ''
this.$confirm(this.$t('trials:hotkeys:message:confirmReset'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
this.loading = true
restoreDefaultShortcutKey({ imageToolType: this.readingTool }).then(res => {
this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // ''
this.getHotkeys(true)
}).catch(() => { this.loading = false })
})
.catch(action => {})
const confirm = await this.$confirm(
this.$t('trials:hotkeys:message:confirmReset'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
try{
await restoreDefaultShortcutKey({ imageToolType: this.readingTool })
this.$message.success(this.$t('trials:hotkeys:message:resetSuccessfully')) // ''
this.getHotkeys(true)
this.loading = false
}catch(e){
this.loading = false
}
},
handleHotkeyVerify(hotkey) {
for (const item of this.hotKeyList) {

View File

@ -21,7 +21,7 @@
</div>
<div class="right-wrapper">
<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>
@ -44,26 +44,30 @@ export default {
},
fileList: [],
loading: false,
currentUser: zzSessionStorage.getItem('userName')
currentUser: zzSessionStorage.getItem('userName'),
COMPANY:process.env.VUE_APP_COMPANY_NAME
}
},
mounted() {
this.getList()
},
methods: {
getList() {
async getList() {
this.loading = true
var param = {
trialId: this.trialId
}
getManualList(param).then(res => {
try{
let res = await getManualList(param)
this.fileList = res.Result
if (this.fileList.length > 0) {
this.preview(this.fileList[0])
}
this.loading = false
}).catch(() => { this.loading = false })
}catch(e){
this.loading = false
}
},
preview(file) {
this.$set(this.selected, 'filePath', file.Path)

View File

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

View File

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

View File

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

View File

@ -15,7 +15,7 @@
</div>
<!-- 文件层级 -->
<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 v-else id="imgList" style="height:100%;">
<div
@ -28,7 +28,14 @@
class="img-box"
@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>
@ -95,10 +102,12 @@ export default {
subjectCode: '',
visistTaskId: '',
taskBlindName: '',
readingTaskState: 2
readingTaskState: 2,
bp: []
}
},
mounted() {
async mounted() {
this.bp = await this.$getBodyPart(this.$route.query.trialId)
if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '')
@ -186,7 +195,7 @@ export default {
}
var arr = bodyPart.split(separator)
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(' | ')
}
@ -263,13 +272,19 @@ export default {
display: inline-block;
box-sizing: border-box;
border-bottom: 2px solid #f3f3f3;
width: 180px;
height: 50px;
line-height: 50px;
cursor: pointer;
// margin-bottom: 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){
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,
hideHandlesIfMoving: false,
renderDashed: false,
digits: 2
}
digits: 2,
},
}
super(props, defaultProps)
@ -48,7 +48,7 @@ export default class LengthTool extends cornerstoneTools.LengthTool {
createNewMeasurement(eventData) {
const goodEventData =
eventData && eventData.currentPoints && eventData.currentPoints.image
console.log('createNewMeasurement: ',goodEventData)
if (!goodEventData) {
console.log(
`required eventData not supplied to tool ${this.name}'s createNewMeasurement`
@ -84,7 +84,8 @@ export default class LengthTool extends cornerstoneTools.LengthTool {
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
}
},
allowedOutsideImage:true
}
}
}

View File

@ -40,7 +40,8 @@ export default class RectangleRoiTool extends cornerstoneTools.RectangleRoiTool
drawHandles: true,
drawHandlesOnHover: false,
hideHandlesIfMoving: false,
renderDashed: false
renderDashed: false,
showStatsText: false
// showMinMax: false,
// showHounsfieldUnits: true
},
@ -531,12 +532,15 @@ function _createTextBoxContent(
minString += ' '
}
otherLines.push(`${minString}${maxString}`)
otherLines.push(`${minString}`)
otherLines.push(`${maxString}`)
}
}
// textLines.push(_formatArea(area, hasPixelSpacing))
// otherLines.forEach(x => textLines.push(x))
if (options.showStatsText) {
textLines.push(_formatArea(area, hasPixelSpacing))
otherLines.forEach(x => textLines.push(x))
}
if (data.hasOwnProperty('remark')) {
if (data.hasOwnProperty('status') && data.status) {
textLines.push(`${data.remark}(${data.status})`)
@ -546,3 +550,11 @@ function _createTextBoxContent(
}
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
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}">
<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>
@ -85,20 +96,20 @@
<template>
<el-table-column
v-for="(qs,index) in globalInfo.adjustedQsList"
v-if="qs.isShow"
:key="index"
prop=""
:label="qs"
:label="qs.questionName"
show-overflow-tooltip
:min-width="index === 3 ? '200' : '200'"
>
<template slot-scope="scope">
<div v-if="readingTaskState<2">
<span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
<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)">
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
</span>
</span> -->
<el-form-item
v-else
style="margin-bottom: 0;"
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
label=""
@ -255,7 +266,7 @@
/>
</el-form-item>
</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">
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
@ -320,7 +331,6 @@ export default {
...mapGetters(['language'])
},
mounted() {
console.log('iRecist')
this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline)
},
methods: {
@ -346,11 +356,12 @@ export default {
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?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 {
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 })
var newWindow = window.open(routeData.href, '_blank')
@ -361,9 +372,10 @@ export default {
return lesion ? lesion.Count : 0
},
handleSave(isPrompt = true) {
return new Promise((resolve, reject) => {
this.$refs['globalRuleForm'].validate(valid => {
if (valid) {
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) => {
@ -392,7 +404,8 @@ export default {
trialId: this.globalInfo.trialId,
visitTaskAnswerList
}
batchSubmitGlobalReadingInfo(params).then(res => {
try {
await batchSubmitGlobalReadingInfo(params)
this.loading = false
if (isPrompt) {
console.log(isPrompt)
@ -400,14 +413,13 @@ export default {
}
this.$emit('getGlInfo')
resolve()
}).catch(() => {
} catch (e) {
this.loading = false
reject()
})
}
} else {
reject()
}
})
})
},
getBeforeAnswer(qsId, row) {
@ -452,23 +464,23 @@ export default {
</script>
<style lang="scss" scoped>
>>>.el-form-item label:before {
/deep/ .el-form-item label:before {
content: '*';
color: #F56C6C;
margin-right: 4px;
}
>>>.el-textarea .el-input__count{
/deep/ .el-textarea .el-input__count{
background: rgba(0,0,0,0);
line-height: normal;
}
>>>.el-form-item{
/deep/ .el-form-item{
margin-bottom: 0px;
}
.global-form{
>>>.el-form-item__content{
/deep/ .el-form-item__content{
padding-bottom: 10px;
}
>>>.form-item .el-form-item__error{
/deep/ .form-item .el-form-item__error{
top: 60%;
}
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -55,6 +55,7 @@
:question-form="questionForm"
:reading-task-state="readingTaskState"
:visit-task-id="visitTaskId"
:calculation-list="calculationList"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
@ -77,8 +78,15 @@
<el-form-item v-if="readingTaskState < 2">
<div style="text-align:center;">
<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="skipTask" v-if="iseCRFShowInDicomReading">
{{ $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>
</el-form-item>
</el-form>
@ -103,7 +111,8 @@
<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 FormItem from './FormItem'
import SignForm from '@/views/trials/components/newSignForm'
@ -131,6 +140,10 @@ export default {
visitTaskId: {
type: String,
required: true
},
iseCRFShowInDicomReading: {
type: Boolean,
required: true
}
},
data() {
@ -145,104 +158,136 @@ export default {
currentUser: zzSessionStorage.getItem('userName'),
readingTaskState: 0,
activeName: 0,
formType: null
formType: null,
classArr: [],
calculationList: []
}
},
mounted() {
this.getQuestionCalculateRelation()
this.getQuestions()
DicomEvent.$on('refreshQuestionAnswer', _ => {
this.getQuestions()
})
},
methods: {
getQuestions() {
async getQuestions() {
this.loading = true
var param = {
readingQuestionCriterionTrialId: this.criterionId,
visitTaskId: this.visitTaskId
}
getTrialReadingQuestion(param).then(res => {
this.readingTaskState = res.OtherInfo.readingTaskState
this.formType = res.OtherInfo.FormType
if (res.OtherInfo.FormType === 2) {
if (res.Result.MultiPage.length > 0) {
res.Result.MultiPage.map((v) => {
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.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.MultiPage
this.activeName = res.Result.MultiPage[0].PageName
}
if (res.Result.PublicPage.length > 0) {
res.Result.PublicPage.map((v) => {
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.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.publicQuestions = res.Result.PublicPage
}
} else {
res.Result.SinglePage.map((v) => {
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.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.SinglePage
try {
const param = {
readingQuestionCriterionTrialId: this.criterionId,
visitTaskId: this.visitTaskId
}
const res = await getTrialReadingQuestion(param)
if (res.IsSuccess) {
this.readingTaskState = res.OtherInfo.readingTaskState
this.formType = res.OtherInfo.FormType
if (res.OtherInfo.FormType === 2) {
if (res.Result.MultiPage.length > 0) {
res.Result.MultiPage.map((v) => {
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.MultiPage
this.activeName = res.Result.MultiPage[0].PageName
}
if (res.Result.PublicPage.length > 0) {
res.Result.PublicPage.map((v) => {
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.publicQuestions = res.Result.PublicPage
}
} else {
res.Result.SinglePage.map((v) => {
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
}).catch(() => { this.loading = false })
} catch (e) {
this.loading = false
}
},
setChild(obj) {
obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
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) {
this.setChild(i.Childrens)
}
})
},
handleSave() {
this.$refs['questions'].validate((valid) => {
if (!valid) return
this.loading = true
var answers = []
for (const k in this.questionForm) {
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
})
})
async getQuestionCalculateRelation() {
try {
let res = await getQuestionCalculateRelation({TrialReadingCriterionId: this.criterionId})
this.calculationList = res.Result
} catch(e) {
console.log(e)
}
},
handleSubmit() {
this.$refs['questions'].validate((valid) => {
if (!valid) return
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
})
async handleSave() {
const valid = await this.$refs['questions'].validate()
if (!valid) return
this.loading = true
const answers = []
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) {
@ -253,7 +298,7 @@ export default {
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var answers = []
for (const k in this.questionForm) {
@ -268,49 +313,80 @@ export default {
},
signInfo: signInfo
}
submitVisitTaskQuestionsInDto(params).then(res => {
try {
const res = await submitVisitTaskQuestionsInDto(params)
this.loading = false
if (res.IsSuccess) {
DicomEvent.$emit('getReportInfo', true)
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.isEdit = false
this.$refs['signForm'].btnLoading = false
this.signVisible = false
this.readingTaskState = 2
window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:globalReview:message:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
DicomEvent.$emit('getNextTask')
})
.catch(action => {
})
// 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}`
// })
const confirm = await this.$confirm(
this.$t('trials:noneDicoms:message:msg1'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
window.location.reload()
}
this.loading = false
}).catch(_ => {
} catch (e) {
this.loading = 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) {
this.questionForm[v] = null
},
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}`"
:prop="question.Id"
:rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
message: '请注明', trigger: ['blur', 'change']},
{ 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']},
]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
>
@ -39,27 +39,27 @@
:disabled="readingTaskState >= 2"
/>
<!-- 下拉框 -->
<!-- <el-select-->
<!-- v-if="question.Type==='select'"-->
<!-- v-model="questionForm[question.Id]"-->
<!-- :disabled="readingTaskState >= 2"-->
<!-- clearable-->
<!-- @change="((val)=>{formItemChange(val, question)})"-->
<!-- >-->
<!-- <el-option-->
<!-- v-for="val in question.TypeValue.split('|')"-->
<!-- :key="val"-->
<!-- :label="val"-->
<!-- :value="val"-->
<!-- />-->
<!-- </el-select>-->
<!-- <el-select-->
<!-- v-if="question.Type==='select'"-->
<!-- v-model="questionForm[question.Id]"-->
<!-- :disabled="readingTaskState >= 2"-->
<!-- clearable-->
<!-- @change="((val)=>{formItemChange(val, question)})"-->
<!-- >-->
<!-- <el-option-->
<!-- v-for="val in question.TypeValue.split('|')"-->
<!-- :key="val"-->
<!-- :label="val"-->
<!-- :value="val"-->
<!-- />-->
<!-- </el-select>-->
<el-select
v-if="question.Type==='select'"
v-model="questionForm[question.Id]"
filterable
:placeholder="$t('common:placeholder:select')"
:disabled="readingTaskState >= 2"
@change="((val)=>{formItemChange(val, qs)})"
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.DictionaryCode">
<el-option
@ -72,9 +72,9 @@
<template v-else-if="question.TypeValue">
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
:key="val.trim()"
:label="val.trim()"
:value="val.trim()"
/>
</template>
</el-select>
@ -91,16 +91,16 @@
:key="item.id"
:label="item.value.toString()"
>
{{item.label}}
{{ item.label }}
</el-radio>
</template>
<template v-else-if="question.TypeValue">
<el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:key="val.trim()"
:label="val.trim()"
>
{{ val }}
{{ val.trim() }}
</el-radio>
</template>
</el-radio-group>
@ -112,23 +112,97 @@
>
<el-checkbox
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:key="val.trim()"
:label="val.trim()"
>
{{ val }}
{{ val.trim() }}
</el-checkbox>
</el-checkbox-group>
<!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" -->
<el-input-number
v-if="question.Type==='number'"
<template 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]"
: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
v-if="question.Type==='upload'"
:action="accept"
action
:accept="accept"
:limit="question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
@ -143,7 +217,6 @@
<div slot="file" slot-scope="{file}">
<img
class="el-upload-list__item-thumbnail"
crossOrigin="Anonymous"
:src="OSSclientConfig.basePath + file.url"
alt=""
>
@ -170,7 +243,7 @@
:visible.sync="imgVisible"
width="600px"
>
<el-image :src="imageUrl" width="100%">
<el-image :src="OSSclientConfig.basePath + imageUrl" width="100%">
<div slot="placeholder" class="image-slot">
{{ $t('trials:readingUnit:qsList:message:loading') }}<span class="dot">...</span>
</div>
@ -186,13 +259,15 @@
:reading-task-state="readingTaskState"
:question-form="questionForm"
:visit-task-id="visitTaskId"
:calculationList="calculationList"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
@formItemNumberChange="formItemNumberChange"
/>
</div>
</template>
<script>
import { uploadReadingAnswerImage } from '@/api/trials'
// import { uploadReadingAnswerImage } from '@/api/trials'
export default {
name: 'FormItem',
props: {
@ -215,6 +290,12 @@ export default {
visitTaskId: {
type: String,
default: ''
},
calculationList: {
type: Array,
default() {
return []
}
}
},
data() {
@ -223,15 +304,25 @@ export default {
accept: '.png,.jpg,.jpeg',
imgVisible: false,
imageUrl: '',
urls: []
urls: [],
digitPlaces: null,
}
},
watch: {
questionForm: {
deep: true,
immediate: true,
handler(v) {
// console.log(v)
handler(v, oldv) {
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.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: {
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) {
if (question.Childrens.length > 0) {
this.resetChild(question.Childrens)
} else {
this.$emit('setFormItemData', { key: question.Id, val: v, question: question})
}
},
resetChild(obj) {
@ -267,7 +523,7 @@ export default {
setFormItemData(obj) {
this.$emit('setFormItemData', obj)
},
uploadScreenshot(param) {
async uploadScreenshot(param) {
if (!this.visitTaskId) return
const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'),
@ -276,18 +532,12 @@ export default {
text: 'Loading',
spinner: 'el-icon-loading'
})
const formData = new FormData()
formData.append('file', param.file)
uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
if (res.IsSuccess) {
this.fileList.push({ url: `${res.Result.Path}` })
this.urls.push(res.Result.Path)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
}
loading.close()
}).catch(() => {
loading.close()
})
var file = await this.fileToBlob(param.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.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
loading.close()
},
handleBeforeUpload(file) {
//
@ -310,7 +560,7 @@ export default {
},
//
handlePictureCardPreview(file) {
this.imageUrl = file.url
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
},
//
@ -328,7 +578,7 @@ export default {
margin-bottom: 0px;
}
.disabled{
>>>.el-upload--picture-card {
/deep/ .el-upload--picture-card {
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>
<div v-loading="loading" class="img-container">
<el-card class="box-card left">
<div v-if="otherInfo && otherInfo.IsReadingShowSubjectInfo" class="title">
<span>{{$t('trials:auditRecord:table:subject')}}{{ otherInfo.SubjectCode }} </span>
<span>({{ otherInfo.TaskBlindName }})</span>
<div class="img-container">
<el-card v-loading="loading" class="box-card left">
<div v-if="isReadingShowSubjectInfo" class="title">
<h4>{{ subjectCode }} </h4>
<h4>{{ taskBlindName }}</h4>
</div>
<el-tabs v-model="activeName" @tab-click="handleClick">
<el-tab-pane :label="$t('trials:clinicaldara:title:currentTask')" name="first" class="left-content">
@ -28,10 +28,16 @@
'is-boxActive': item.Id === currentFileId
}"
class="img-box"
style="text-overflow: ellipsis;overflow: hidden;white-space: nowrap;"
@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>
@ -42,7 +48,7 @@
<div style="height:100%;">
<!-- 文件层级 -->
<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 v-else>
<div
@ -54,9 +60,15 @@
class="img-box"
@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>
</el-tab-pane>
@ -64,7 +76,7 @@
</el-card>
<!-- 预览图像 -->
<el-card class="box-card right">
<el-card v-loading="loading" class="box-card right">
<div style="width:100%;height: 100%;">
<Preview
v-if="previewImage.imgList.length > 0"
@ -79,20 +91,25 @@
</el-card>
<el-card class="box-card" style="width:400px;height:100%;padding: 10px;margin-left:10px;overflow-y: auto;">
<el-button
v-if="otherInfo && otherInfo.IsExistsClinicalData"
type="primary"
size="mini"
@click="previewCD"
>
{{ $t('trials:crcUpload:label:clinicalData') }}
</el-button>
<div style="text-align:right;">
<el-button
v-if="otherInfo && otherInfo.IsExistsClinicalData"
type="text"
@click="previewCD"
>
{{ $t('trials:crcUpload:label:clinicalData') }}
</el-button>
</div>
<Criterions
v-if="otherInfo && visitTaskId!== '' && subjectId!== '' && readingCategory!==null && readingCategory!==4"
:trial-id="trialId"
:subject-id="subjectId"
:visit-task-id="visitTaskId"
: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>
</div>
@ -127,9 +144,33 @@ export default {
type: String,
required: true
},
taskBlindName: {
type: String,
required: true
},
readingCategory: {
type: Number,
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() {
@ -155,7 +196,9 @@ export default {
associatedList: [],
currentTaskId: '',
otherInfo: null,
isReadingShowPreviousResults: false
isReadingShowPreviousResults: false,
bp: [],
openWindow: null
}
},
computed: {
@ -163,11 +206,17 @@ export default {
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.getNoneDicomList(this.isReadingShowPreviousResults)
},
beforeDestroy() {
if (this.openWindow) {
this.openWindow.close()
}
},
methods: {
// Dicom
getNoneDicomList() {
@ -248,18 +297,21 @@ export default {
})
},
handleImageRead(task) {
if (this.openWindow) {
this.openWindow.close()
}
this.currentTaskId = task.VisitTaskId
var criterionType = this.$router.currentRoute.query.criterionType
var readingTool = this.$router.currentRoute.query.readingTool
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
var criterionType = this.criterionType
var readingTool = this.readingTool
var isReadingTaskViewInOrder = this.isReadingTaskViewInOrder
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
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({
// path: `/readingPage?subjectId=${this.subjectId}&trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&TokenKey=${token}`
// })
const routeData = this.$router.resolve({ path })
window.open(routeData.href, '_blank')
this.openWindow = window.open(routeData.href, '_blank')
},
previewCD() {
var token = getToken()
@ -280,7 +332,7 @@ export default {
}
var arr = bodyPart.split(separator)
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(' | ')
}
@ -293,7 +345,7 @@ export default {
flex: 1;
width: 100%;
height: 100%;
padding: 10px;
padding-bottom: 10px;
display: flex;
::-webkit-scrollbar {
width: 7px;
@ -303,7 +355,7 @@ export default {
border-radius: 10px;
background: #d0d0d0;
}
>>>.el-card__body{
/deep/ .el-card__body{
padding: 0px;
}
}
@ -317,37 +369,43 @@ export default {
width:240px;
height: 100%;
>>>.el-card__body{
/deep/ .el-card__body{
height: 100%;
width: 100%;
display: flex;
flex-direction: column;
}
.title{
height: 40px;
line-height: 40px;
// height: 40px;
// line-height: 40px;
border: 1ppx solid;
border: 1px solid #ebe7e7;
padding-left: 10px;
// padding-left: 10px;
background-color: #4e4e4e;
color: #ffffff;
h4{
padding: 5px 0px;
margin: 0;
text-align: center;
background-color: #4c4c4c;
}
}
.left-content{
flex: 1;
overflow-y: auto;
}
>>>.el-tabs{
/deep/ .el-tabs{
height: 100%;
display:flex;
flex-direction: column;
}
>>>.el-tabs__header{
/deep/ .el-tabs__header{
height: 40px;
padding: 0 5px;
margin-bottom: 5px;
}
>>>.el-tabs__content{
/deep/ .el-tabs__content{
flex: 1;
overflow-y: auto;
padding: 0 5px;
@ -357,13 +415,19 @@ export default {
display: inline-block;
box-sizing: border-box;
border-bottom: 2px solid #f3f3f3;
width: 180px;
height: 50px;
line-height: 50px;
cursor: pointer;
// margin-bottom: 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){
margin-bottom: 0px;
}
@ -379,7 +443,7 @@ export default {
flex: 1;
height: 100%;
margin-left: 10px;
>>>.el-card__body{
/deep/ .el-card__body{
height: 100%;
width: 100%;
}

View File

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

View File

@ -26,6 +26,14 @@
>
{{ $t('trials:oncologyReview:button:clinicalData') }}
</el-button>
<el-button
type="primary"
size="small"
@click="skipTask"
>
<!-- 跳过 -->
{{ $t('trials:readingReport:button:skip') }}
</el-button>
<!-- 保存 -->
<el-button
v-if="oncologyInfo.ReadingTaskState < 2"
@ -93,7 +101,7 @@
<span>{{ $fd('YesOrNo', scope.row.IsHaveChange ) }}</span>
<!-- 查看详情 -->
<el-button
v-if="scope.row.IsHaveChange && !!oncologyInfo.GlobalTaskId"
v-if="scope.row.IsHaveChange && oncologyInfo.GlobalTaskId"
type="text"
style="margin-left:5px;"
@click="handleViewDetail(oncologyInfo.GlobalTaskId)"
@ -122,18 +130,24 @@
<!-- 结论 -->
<el-table-column
prop="EvaluationResult"
:label="$t('trials:oncologyReview:title:findings')"
show-overflow-tooltip
width="150"
>
<template slot="header">
<div>
<span>{{ $t('trials:oncologyReview:title:findings') }}</span>
<span style="color:red">*</span>
</div>
</template>
<template slot-scope="scope">
<el-select
v-if="oncologyInfo.ReadingTaskState < 2"
v-if="oncologyInfo.ReadingTaskState < 2 && !scope.row.IsBaseLine"
v-model="scope.row.EvaluationResult"
:placeholder="$t('common:ruleMessage:select')"
>
<el-option
v-for="item in assessTypeList"
v-show="item.Code !== '-1'"
:key="item.Id"
:label="item.Value"
:value="item.Code"
@ -156,14 +170,14 @@
<div>
<!-- 原因 -->
<span>{{ $t('trials:oncologyReview:title:reason') }}</span>
<span style="color:red">*</span>
<span style="color:red">!</span>
</div>
</el-tooltip>
</template>
<template slot-scope="scope">
<el-input
v-if="oncologyInfo.ReadingTaskState < 2"
v-if="oncologyInfo.ReadingTaskState < 2 && !scope.row.IsBaseLine"
v-model="scope.row.EvaluationReason"
/>
<span v-else>{{ scope.row.EvaluationReason }}</span>
@ -207,6 +221,12 @@
show-overflow-tooltip
width="200"
/>
<el-table-column
prop="VisitName"
:label="$t('trials:globalReview:table:cutOffVisitName')"
show-overflow-tooltip
width="200"
/>
<el-table-column
:label="$t('common:action:action')"
width="200"
@ -241,8 +261,12 @@
</template>
<script>
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 { 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 SignForm from '@/views/trials/components/newSignForm'
export default {
@ -331,9 +355,10 @@ export default {
}
},
methods: {
getList() {
async getList() {
this.loading = true
getOncologyReadingInfo({ visitTaskId: this.visitTaskId }).then(res => {
try {
const res = await getOncologyReadingInfo({ visitTaskId: this.visitTaskId })
var questions = []
if (res.Result.OncologyVisits.length > 0) {
var task = res.Result.OncologyVisits[0]
@ -345,7 +370,9 @@ export default {
this.assessTypeList = res.Result.AssessTypeList
this.oncologyInfo = res.Result
this.loading = false
}).catch(() => { this.loading = false })
} catch (e) {
this.loading = false
}
},
getAssessType(val) {
var idx = this.assessTypeList.findIndex(i => i.Code === val)
@ -356,62 +383,81 @@ export default {
}
},
handleSave(isPrompt) {
this.loading = true
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 {
return new Promise(async(resolve, reject) => {
this.loading = true
var oncologyQuestionList = []
this.oncologyInfo.OncologyVisits.map(item => {
if (item.EvaluationResult) {
oncologyQuestionList.push(
{
visitTaskId: item.VisitTaskId,
evaluationResult: item.EvaluationResult,
evaluationReason: item.EvaluationReason
}
)
// var index = this.oncologyInfo.OncologyVisits.findIndex(item => !item.EvaluationResult && !item.IsBaseLine)
var isDiffer = this.checkDifferResult()
if (isDiffer) {
this.loading = false
const confirm = await this.$confirm(
this.$t('trials:oncologyReview:message:msg2'),
{
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
}
})
var params = {
oncologyTaskId: this.visitTaskId,
oncologyQuestionList: oncologyQuestionList
}
return new Promise((resolve, reject) => {
setOncologyReadingInfo(params).then(res => {
try {
await setOncologyReadingInfo(params)
this.loading = false
this.getList()
if (isPrompt) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
resolve(true)
}).catch(_ => {
} catch (e) {
this.loading = 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) {
if (isSign) {
@ -420,17 +466,16 @@ export default {
this.signVisible = false
}
},
handleConfirm() {
this.handleSave(false).then(res => {
if (res) {
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}
})
async handleConfirm() {
const res = await this.handleSave(false)
if (res) {
const { ImageAssessmentReportConfirmation } = const_.processSignature
this.signCode = ImageAssessmentReportConfirmation
this.signVisible = true
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var params = {
data: {
@ -438,7 +483,8 @@ export default {
},
signInfo: signInfo
}
submitOncologyReadingInfo(params).then(res => {
try {
const res = await submitOncologyReadingInfo(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.isEdit = false
@ -448,43 +494,47 @@ export default {
// window.opener.postMessage('refreshTaskList', window.location)
//
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
}).catch(_ => {
} catch (e) {
this.loading = false
this.$refs['signForm'].btnLoading = false
})
}
},
getPriorList() {
async getPriorList() {
this.priorLoading = true
getReadingPastResultList({ visitTaskId: this.visitTaskId }).then(res => {
try {
const res = await getReadingPastResultList({ visitTaskId: this.visitTaskId })
this.priorList = res.Result
this.priorLoading = false
}).catch(() => { this.priorLoading = false })
} catch (e) {
this.priorLoading = false
}
},
handleViewDetail(visitTaskId) {
if (this.openWindow) {
@ -514,6 +564,28 @@ export default {
path: `/clinicalData?subjectId=${this.oncologyInfo.SubjectId}&trialId=${this.trialId}&visitTaskId=${this.oncologyInfo.OncologyTaskId}&TokenKey=${token}`
})
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: [
new CopyPlugin([
{ 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/cornerstoneWADOImageLoaderWebWorker.min.js', to: 'webWorker.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.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.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.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.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.worker.js', to: 'ffmpeg-core.worker.js' },
{
from: path.resolve(__dirname, './static'),
to: path.resolve(__dirname, './dist/static'),