Compare commits
4 Commits
6c36c48b82
...
946203f124
| Author | SHA1 | Date |
|---|---|---|
|
|
946203f124 | |
|
|
f0eb814492 | |
|
|
47b05526a2 | |
|
|
f7afca6e73 |
|
|
@ -408,3 +408,19 @@ export function changeSegmentationSavedStatus(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 图像数据匿名
|
||||||
|
export function studyMaskImage(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/studyMaskImage`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 撤销匿名
|
||||||
|
export function studyUndoMaskImage(data) {
|
||||||
|
return request({
|
||||||
|
url: `/Study/studyUndoMaskImage`,
|
||||||
|
method: 'post',
|
||||||
|
data
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -23,17 +23,11 @@
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
||||||
HU: {{ mousePosition.mo }}
|
HU: {{ mousePosition.mo }}</div>
|
||||||
</div>
|
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">SUVbw(g/ml): {{ mousePosition.suv.toFixed(3)
|
||||||
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">
|
}}</div>
|
||||||
SUVbw(g/ml): {{ mousePosition.suv.toFixed(3) }}
|
<div v-else-if="mousePosition.mo">Density: {{ mousePosition.mo }}</div>
|
||||||
</div>
|
<div>W*H: {{ dicomInfo.size }}</div>
|
||||||
<div v-else-if="mousePosition.mo">
|
|
||||||
Density: {{ mousePosition.mo }}
|
|
||||||
</div>
|
|
||||||
<div>
|
|
||||||
W*H: {{ dicomInfo.size }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>Zoom: {{ dicomInfo.zoom }}</div>
|
<div>Zoom: {{ dicomInfo.zoom }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -56,19 +50,11 @@
|
||||||
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
|
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
|
||||||
@mousedown="sliderMousedown($event)" />
|
@mousedown="sliderMousedown($event)" />
|
||||||
</div>
|
</div>
|
||||||
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
|
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">{{ markers.top }}</div>
|
||||||
{{ markers.top }}
|
<div style="position: absolute;top: 50%;right: 15px;color: #f44336;">{{ markers.right }}</div>
|
||||||
</div>
|
|
||||||
<div style="position: absolute;top: 50%;right: 15px;color: #f44336;">
|
|
||||||
{{ markers.right }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style="position: absolute;left: 50%;bottom: 15px;color: #f44336;">
|
<div style="position: absolute;left: 50%;bottom: 15px;color: #f44336;">{{ markers.bottom }}</div>
|
||||||
{{ markers.bottom }}
|
<div style="position: absolute;top: 50%;left: 15px;color: #f44336;">{{ markers.left }}</div>
|
||||||
</div>
|
|
||||||
<div style="position: absolute;top: 50%;left: 15px;color: #f44336;">
|
|
||||||
{{ markers.left }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="info-instance">
|
<div class="info-instance">
|
||||||
<!-- <div v-show="dicomInfo.pixel">
|
<!-- <div v-show="dicomInfo.pixel">
|
||||||
|
|
@ -101,6 +87,7 @@ import invertOrientationString from '@/views/trials/trials-panel/reading/dicoms/
|
||||||
import calculateSUV from '@/views/trials/trials-panel/reading/dicoms/tools/calculateSUV'
|
import calculateSUV from '@/views/trials/trials-panel/reading/dicoms/tools/calculateSUV'
|
||||||
// import requestPoolManager from '@/utils/request-pool'
|
// import requestPoolManager from '@/utils/request-pool'
|
||||||
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
|
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
|
||||||
|
import Note_RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/Note_RectangleRoiTool'
|
||||||
cornerstoneTools.external.cornerstone = cornerstone
|
cornerstoneTools.external.cornerstone = cornerstone
|
||||||
cornerstoneTools.external.Hammer = Hammer
|
cornerstoneTools.external.Hammer = Hammer
|
||||||
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
||||||
|
|
@ -117,7 +104,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
NSTip() {
|
NSTip() {
|
||||||
return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
|
return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -130,7 +117,7 @@ export default {
|
||||||
seriesNumber: '',
|
seriesNumber: '',
|
||||||
imageIds: [],
|
imageIds: [],
|
||||||
currentImageIdIndex: 0,
|
currentImageIdIndex: 0,
|
||||||
firstImageLoading: false
|
firstImageLoading: false,
|
||||||
// preventCache: true
|
// preventCache: true
|
||||||
},
|
},
|
||||||
dicomInfo: {
|
dicomInfo: {
|
||||||
|
|
@ -150,14 +137,14 @@ export default {
|
||||||
wwwc: '',
|
wwwc: '',
|
||||||
zoom: 0,
|
zoom: 0,
|
||||||
location: '',
|
location: '',
|
||||||
fps: 5
|
fps: 5,
|
||||||
},
|
},
|
||||||
toolState: {
|
toolState: {
|
||||||
initialized: false,
|
initialized: false,
|
||||||
activeTool: 'none',
|
activeTool: 'none',
|
||||||
dicomInfoVisible: false,
|
dicomInfoVisible: false,
|
||||||
clipPlaying: false,
|
clipPlaying: false,
|
||||||
viewportInvert: false
|
viewportInvert: false,
|
||||||
},
|
},
|
||||||
loadImagePromise: null,
|
loadImagePromise: null,
|
||||||
AnnotationSync: null,
|
AnnotationSync: null,
|
||||||
|
|
@ -168,18 +155,20 @@ export default {
|
||||||
sliderInfo: {
|
sliderInfo: {
|
||||||
oldB: null,
|
oldB: null,
|
||||||
oldM: null,
|
oldM: null,
|
||||||
isMove: false
|
isMove: false,
|
||||||
},
|
},
|
||||||
mousePosition: { x: '', y: '', mo: '' },
|
mousePosition: { x: '', y: '', mo: '' },
|
||||||
markers: { top: '', right: '', bottom: '', left: '' },
|
markers: { top: '', right: '', bottom: '', left: '' },
|
||||||
orientationMarkers: [],
|
orientationMarkers: [],
|
||||||
originalMarkers: [],
|
originalMarkers: [],
|
||||||
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') }
|
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') },
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
mounted() {
|
mounted() {
|
||||||
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
|
this.type = this.$router.currentRoute.query.type
|
||||||
|
? this.$router.currentRoute.query.type
|
||||||
|
: ''
|
||||||
this.canvas = this.$refs.canvas
|
this.canvas = this.$refs.canvas
|
||||||
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
|
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
|
||||||
this.canvas.addEventListener(
|
this.canvas.addEventListener(
|
||||||
|
|
@ -200,7 +189,10 @@ export default {
|
||||||
document.addEventListener('mousemove', (e) => {
|
document.addEventListener('mousemove', (e) => {
|
||||||
this.sliderMousemove(e)
|
this.sliderMousemove(e)
|
||||||
})
|
})
|
||||||
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
|
this.canvas.addEventListener(
|
||||||
|
'cornerstonetoolsstackscroll',
|
||||||
|
this.stackScrollCallback
|
||||||
|
)
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -210,7 +202,11 @@ export default {
|
||||||
this.stack.seriesId = dicomSeries.seriesId
|
this.stack.seriesId = dicomSeries.seriesId
|
||||||
this.stack.seriesNumber = dicomSeries.seriesNumber
|
this.stack.seriesNumber = dicomSeries.seriesNumber
|
||||||
this.stack.imageIds = dicomSeries.imageIds
|
this.stack.imageIds = dicomSeries.imageIds
|
||||||
this.stack.currentImageIdIndex = dicomSeries.imageIdIndex && dicomSeries.imageIdIndex < dicomSeries.imageIds.length ? dicomSeries.imageIdIndex : 0
|
this.stack.currentImageIdIndex =
|
||||||
|
dicomSeries.imageIdIndex &&
|
||||||
|
dicomSeries.imageIdIndex < dicomSeries.imageIds.length
|
||||||
|
? dicomSeries.imageIdIndex
|
||||||
|
: 0
|
||||||
this.stack.firstImageLoading = true
|
this.stack.firstImageLoading = true
|
||||||
this.stack.description = dicomSeries.description
|
this.stack.description = dicomSeries.description
|
||||||
this.toolState.viewportInvert = false
|
this.toolState.viewportInvert = false
|
||||||
|
|
@ -226,13 +222,17 @@ export default {
|
||||||
this.toolState.clipPlaying = false
|
this.toolState.clipPlaying = false
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
||||||
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
|
cornerstone
|
||||||
.then(image => {
|
.loadAndCacheImage(
|
||||||
|
this.stack.imageIds[this.stack.currentImageIdIndex]
|
||||||
|
)
|
||||||
|
.then((image) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
|
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
|
||||||
this.onFirstImageLoaded(image)
|
this.onFirstImageLoaded(image)
|
||||||
}
|
}
|
||||||
}).catch((error) => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (error.error && error.error.message) {
|
if (error.error && error.error.message) {
|
||||||
this.$alert(error.error.message)
|
this.$alert(error.error.message)
|
||||||
|
|
@ -255,15 +255,17 @@ export default {
|
||||||
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
||||||
|
|
||||||
if (apiTool) {
|
if (apiTool) {
|
||||||
const toolAlreadyAddedToElement = cornerstoneTools.getToolForElement(
|
const toolAlreadyAddedToElement =
|
||||||
element,
|
cornerstoneTools.getToolForElement(element, apiTool)
|
||||||
apiTool
|
|
||||||
)
|
|
||||||
if (!toolAlreadyAddedToElement) {
|
if (!toolAlreadyAddedToElement) {
|
||||||
if (toolName === 'RectangleRoi') {
|
if (toolName === 'RectangleRoi') {
|
||||||
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true, showStatsText: true } })
|
cornerstoneTools.addToolForElement(element, apiTool, {
|
||||||
|
configuration: { showMinMax: true, showStatsText: true },
|
||||||
|
})
|
||||||
} else if (toolName === 'EllipticalRoi') {
|
} else if (toolName === 'EllipticalRoi') {
|
||||||
cornerstoneTools.addToolForElement(element, apiTool, { configuration: { showMinMax: true } })
|
cornerstoneTools.addToolForElement(element, apiTool, {
|
||||||
|
configuration: { showMinMax: true },
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
cornerstoneTools.addToolForElement(element, apiTool)
|
cornerstoneTools.addToolForElement(element, apiTool)
|
||||||
}
|
}
|
||||||
|
|
@ -287,8 +289,28 @@ export default {
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.WwwcRegionTool)) {
|
if (
|
||||||
cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool)
|
!cornerstoneTools.getToolForElement(element, Note_RectangleRoiTool)
|
||||||
|
) {
|
||||||
|
cornerstoneTools.addToolForElement(element, Note_RectangleRoiTool, {
|
||||||
|
configuration: {
|
||||||
|
color: '#f00',
|
||||||
|
lineWidth: 0.5,
|
||||||
|
drawHandles: false,
|
||||||
|
fillColor: 'rgba(0, 0, 0, 1)',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
!cornerstoneTools.getToolForElement(
|
||||||
|
element,
|
||||||
|
cornerstoneTools.WwwcRegionTool
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
cornerstoneTools.addToolForElement(
|
||||||
|
element,
|
||||||
|
cornerstoneTools.WwwcRegionTool
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!cornerstoneTools.getToolForElement(
|
!cornerstoneTools.getToolForElement(
|
||||||
|
|
@ -347,7 +369,9 @@ export default {
|
||||||
// var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
|
// var instanceId = image.imageId.split('/')[image.imageId.split('/').length - 1]
|
||||||
// instanceId = instanceId.split('.')[0]
|
// instanceId = instanceId.split('.')[0]
|
||||||
// this.stack.instanceId = instanceId
|
// this.stack.instanceId = instanceId
|
||||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
this.height =
|
||||||
|
(this.stack.currentImageIdIndex * 100) /
|
||||||
|
(this.stack.imageIds.length - 1)
|
||||||
this.resetWwwc()
|
this.resetWwwc()
|
||||||
},
|
},
|
||||||
onNewImage(e) {
|
onNewImage(e) {
|
||||||
|
|
@ -379,21 +403,30 @@ export default {
|
||||||
if (this.dicomInfo.thick) {
|
if (this.dicomInfo.thick) {
|
||||||
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
||||||
}
|
}
|
||||||
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === e.detail.image.imageId)
|
const newImageIdIndex = this.stack.imageIds.findIndex(
|
||||||
|
(i) => i === e.detail.image.imageId
|
||||||
|
)
|
||||||
if (newImageIdIndex === -1) return
|
if (newImageIdIndex === -1) return
|
||||||
this.stack.currentImageIdIndex = newImageIdIndex
|
this.stack.currentImageIdIndex = newImageIdIndex
|
||||||
this.stack.imageIdIndex = newImageIdIndex
|
this.stack.imageIdIndex = newImageIdIndex
|
||||||
this.series.imageIdIndex = newImageIdIndex
|
this.series.imageIdIndex = newImageIdIndex
|
||||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
this.height =
|
||||||
|
(this.stack.currentImageIdIndex * 100) /
|
||||||
|
(this.stack.imageIds.length - 1)
|
||||||
this.resetWwwc()
|
this.resetWwwc()
|
||||||
},
|
},
|
||||||
stackScrollCallback(e) {
|
stackScrollCallback(e) {
|
||||||
const { detail } = e
|
const { detail } = e
|
||||||
if (this.isScrollSync) {
|
if (this.isScrollSync) {
|
||||||
this.$emit('scrollSync', { canvasIndex: this.canvasIndex, direction: detail.direction })
|
this.$emit('scrollSync', {
|
||||||
|
canvasIndex: this.canvasIndex,
|
||||||
|
direction: detail.direction,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
this.stack.currentImageIdIndex = e.detail.newImageIdIndex
|
this.stack.currentImageIdIndex = e.detail.newImageIdIndex
|
||||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
this.height =
|
||||||
|
(this.stack.currentImageIdIndex * 100) /
|
||||||
|
(this.stack.imageIds.length - 1)
|
||||||
// var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
|
// var priority = new Date(new Date().setHours(23, 59, 59, 999)).getTime()
|
||||||
|
|
||||||
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
|
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, priority)
|
||||||
|
|
@ -408,7 +441,9 @@ export default {
|
||||||
if (date) {
|
if (date) {
|
||||||
date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
|
date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
|
||||||
}
|
}
|
||||||
if (time) { time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}` }
|
if (time) {
|
||||||
|
time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
|
||||||
|
}
|
||||||
return time ? `${date} ${time}` : `${date} 00:00:00`
|
return time ? `${date} ${time}` : `${date} 00:00:00`
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -453,7 +488,7 @@ export default {
|
||||||
top: oppositeColumn,
|
top: oppositeColumn,
|
||||||
bottom: column,
|
bottom: column,
|
||||||
left: oppositeRow,
|
left: oppositeRow,
|
||||||
right: row
|
right: row,
|
||||||
}
|
}
|
||||||
if (!markers) {
|
if (!markers) {
|
||||||
return
|
return
|
||||||
|
|
@ -500,13 +535,7 @@ export default {
|
||||||
if (image.color) {
|
if (image.color) {
|
||||||
stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
|
stats.storedPixels = this.getRGBPixels(element, x, y, 1, 1)
|
||||||
} else {
|
} else {
|
||||||
stats.storedPixels = cornerstone.getStoredPixels(
|
stats.storedPixels = cornerstone.getStoredPixels(element, x, y, 1, 1)
|
||||||
element,
|
|
||||||
x,
|
|
||||||
y,
|
|
||||||
1,
|
|
||||||
1
|
|
||||||
)
|
|
||||||
stats.sp = stats.storedPixels[0]
|
stats.sp = stats.storedPixels[0]
|
||||||
stats.mo = stats.sp * image.slope + image.intercept
|
stats.mo = stats.sp * image.slope + image.intercept
|
||||||
stats.suv = calculateSUV(image, stats.sp)
|
stats.suv = calculateSUV(image, stats.sp)
|
||||||
|
|
@ -533,7 +562,8 @@ export default {
|
||||||
if (enabledElement.image.color) {
|
if (enabledElement.image.color) {
|
||||||
for (row = 0; row < height; row++) {
|
for (row = 0; row < height; row++) {
|
||||||
for (column = 0; column < width; column++) {
|
for (column = 0; column < width; column++) {
|
||||||
spIndex = ((row + y) * enabledElement.image.columns + (column + x)) * 4
|
spIndex =
|
||||||
|
((row + y) * enabledElement.image.columns + (column + x)) * 4
|
||||||
const red = pixelData[spIndex]
|
const red = pixelData[spIndex]
|
||||||
const green = pixelData[spIndex + 1]
|
const green = pixelData[spIndex + 1]
|
||||||
const blue = pixelData[spIndex + 2]
|
const blue = pixelData[spIndex + 2]
|
||||||
|
|
@ -551,7 +581,8 @@ export default {
|
||||||
},
|
},
|
||||||
sliderMousedown(e) {
|
sliderMousedown(e) {
|
||||||
var boxHeight = this.$refs['sliderBox'].clientHeight
|
var boxHeight = this.$refs['sliderBox'].clientHeight
|
||||||
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
this.sliderInfo.oldB =
|
||||||
|
(parseInt(e.srcElement.style.top) * boxHeight) / 100
|
||||||
this.sliderInfo.oldM = e.clientY
|
this.sliderInfo.oldM = e.clientY
|
||||||
this.sliderInfo.isMove = true
|
this.sliderInfo.isMove = true
|
||||||
e.stopImmediatePropagation()
|
e.stopImmediatePropagation()
|
||||||
|
|
@ -564,9 +595,14 @@ export default {
|
||||||
var boxHeight = this.$refs['sliderBox'].clientHeight
|
var boxHeight = this.$refs['sliderBox'].clientHeight
|
||||||
if (PX < 0) return
|
if (PX < 0) return
|
||||||
if (PX > boxHeight) return
|
if (PX > boxHeight) return
|
||||||
var height = PX * 100 / boxHeight
|
var height = (PX * 100) / boxHeight
|
||||||
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
|
var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
|
||||||
index = index > this.stack.imageIds.length ? this.stack.imageIds.length : index < 0 ? 0 : index
|
index =
|
||||||
|
index > this.stack.imageIds.length
|
||||||
|
? this.stack.imageIds.length
|
||||||
|
: index < 0
|
||||||
|
? 0
|
||||||
|
: index
|
||||||
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
|
// if (!cornerstone.imageCache.getImageLoadObject(this.stack.imageIds[index])) return
|
||||||
this.height = height
|
this.height = height
|
||||||
if (this.stack.currentImageIdIndex !== index) {
|
if (this.stack.currentImageIdIndex !== index) {
|
||||||
|
|
@ -578,9 +614,9 @@ export default {
|
||||||
},
|
},
|
||||||
goViewer(e) {
|
goViewer(e) {
|
||||||
// console.log(this.$refs['sliderBox'].clientHeight)
|
// console.log(this.$refs['sliderBox'].clientHeight)
|
||||||
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
var height = (e.offsetY * 100) / this.$refs['sliderBox'].clientHeight
|
||||||
this.height = height
|
this.height = height
|
||||||
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
|
var index = Math.trunc((this.stack.imageIds.length * this.height) / 100)
|
||||||
scroll(this.canvas, index)
|
scroll(this.canvas, index)
|
||||||
},
|
},
|
||||||
onClipStopped() {
|
onClipStopped() {
|
||||||
|
|
@ -673,10 +709,7 @@ export default {
|
||||||
}
|
}
|
||||||
this.toolState.clipPlaying = true
|
this.toolState.clipPlaying = true
|
||||||
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
|
cornerstoneTools.playClip(this.canvas, this.dicomInfo.fps)
|
||||||
cornerstoneTools.getToolState(
|
cornerstoneTools.getToolState(this.canvas, 'playClip').data[0].loop = true
|
||||||
this.canvas,
|
|
||||||
'playClip'
|
|
||||||
).data[0].loop = true
|
|
||||||
},
|
},
|
||||||
setFps(fps) {
|
setFps(fps) {
|
||||||
this.dicomInfo.fps = fps
|
this.dicomInfo.fps = fps
|
||||||
|
|
@ -712,8 +745,8 @@ export default {
|
||||||
invert: false,
|
invert: false,
|
||||||
preventZoomOutsideImage: false,
|
preventZoomOutsideImage: false,
|
||||||
minScale: 0.1,
|
minScale: 0.1,
|
||||||
maxScale: 20.0
|
maxScale: 20.0,
|
||||||
}
|
},
|
||||||
})
|
})
|
||||||
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
|
cornerstoneTools.setToolActive('Zoom', { mouseButtonMask: 1 })
|
||||||
this.toolState.activeTool = 'zoom'
|
this.toolState.activeTool = 'zoom'
|
||||||
|
|
@ -797,9 +830,110 @@ export default {
|
||||||
setToolPassive(toolName) {
|
setToolPassive(toolName) {
|
||||||
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
|
cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
|
||||||
},
|
},
|
||||||
|
async reloadImage(newImageId = null) {
|
||||||
|
// 1. 获取当前imageId(如果未指定新imageId)
|
||||||
|
let element = this.canvas
|
||||||
|
this.stack.imageIds.splice(this.stack.currentImageIdIndex, 1, newImageId)
|
||||||
|
const currentImageId =
|
||||||
|
newImageId || cornerstone.getImage(element)?.imageId
|
||||||
|
|
||||||
|
if (!currentImageId) {
|
||||||
|
console.error('没有找到可用的imageId')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 清除该影像关联的工具状态(标注数据)
|
||||||
|
this.clearToolStateForImage(element, currentImageId)
|
||||||
|
|
||||||
|
// 3. 从缓存中移除该影像
|
||||||
|
this.removeImageFromCache(currentImageId)
|
||||||
|
|
||||||
|
// 4. 重新加载并渲染
|
||||||
|
await this.loadAndRenderImage(element, currentImageId)
|
||||||
|
},
|
||||||
|
clearToolStateForImage(element, imageId) {
|
||||||
|
// 获取全局状态管理器
|
||||||
|
const globalToolStateManager =
|
||||||
|
cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||||
|
|
||||||
|
if (globalToolStateManager) {
|
||||||
|
// 方式1:清空该影像的全部工具数据
|
||||||
|
globalToolStateManager.clearImageIdToolState(imageId)
|
||||||
|
console.log(`已清除影像 ${imageId} 的所有标注数据`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 方式2:如果使用元素级别的状态管理器
|
||||||
|
const elementToolStateManager =
|
||||||
|
cornerstoneTools.getElementToolStateManager(element)
|
||||||
|
if (elementToolStateManager && elementToolStateManager.get(element)) {
|
||||||
|
// 清空该元素上当前显示影像的数据
|
||||||
|
elementToolStateManager.clear(element)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeImageFromCache(imageId) {
|
||||||
|
const imageCache = cornerstone.imageCache
|
||||||
|
|
||||||
|
if (imageCache && imageCache[imageId]) {
|
||||||
|
// 从缓存中移除
|
||||||
|
delete imageCache[imageId]
|
||||||
|
console.log(`已从缓存中移除影像: ${imageId}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 也可以使用官方API(如果可用)
|
||||||
|
if (typeof cornerstone.imageCache.removeImage === 'function') {
|
||||||
|
cornerstone.imageCache.removeImageLoadObject(imageId)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async loadAndRenderImage(element, imageId) {
|
||||||
|
try {
|
||||||
|
// 1. 清除当前画布内容(可选)
|
||||||
|
const canvas = element.querySelector('canvas')
|
||||||
|
if (canvas) {
|
||||||
|
const ctx = canvas.getContext('2d')
|
||||||
|
ctx.clearRect(0, 0, canvas.width, canvas.height)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 重新加载图像(强制从源头重新获取)
|
||||||
|
const image = await cornerstone.loadAndCacheImage(imageId)
|
||||||
|
|
||||||
|
// 3. 获取或创建视口设置
|
||||||
|
let viewport = cornerstone.getViewport(element)
|
||||||
|
if (!viewport) {
|
||||||
|
viewport = cornerstone.getDefaultViewport(element, image)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. 显示图像
|
||||||
|
cornerstone.displayImage(element, image, viewport)
|
||||||
|
|
||||||
|
// 5. 触发重绘
|
||||||
|
cornerstone.updateImage(element)
|
||||||
|
|
||||||
|
console.log(`影像 ${imageId} 重新加载并渲染完成`)
|
||||||
|
|
||||||
|
return image
|
||||||
|
} catch (error) {
|
||||||
|
console.error('加载图像失败:', error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getNote_RectangleRoi() {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
let toolInfo = cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
|
||||||
|
let image = cornerstone.getImage(this.canvas)
|
||||||
|
resolve({ toolInfo, image })
|
||||||
|
})
|
||||||
|
// console.log(
|
||||||
|
// cornerstoneTools.getToolState(this.canvas, 'Note_RectangleRoi')
|
||||||
|
// )
|
||||||
|
// console.log(cornerstone.getImage(this.canvas))
|
||||||
|
// let image = cornerstone.getImage(this.canvas)
|
||||||
|
// // cornerstone.imageCache.removeImageLoadObject(image.imageId)
|
||||||
|
|
||||||
|
// this.reloadImage(this.canvas, image.imageId)
|
||||||
|
},
|
||||||
setToolActive(toolName) {
|
setToolActive(toolName) {
|
||||||
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
||||||
mouseButtonMask: 1
|
mouseButtonMask: 1,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
setAllToolsPassive() {
|
setAllToolsPassive() {
|
||||||
|
|
@ -833,7 +967,7 @@ export default {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
|
cornerstoneTools.setToolEnabledForElement(this.canvas, 'ReferenceLines', {
|
||||||
synchronizationContext: synchronizer
|
synchronizationContext: synchronizer,
|
||||||
})
|
})
|
||||||
|
|
||||||
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
|
// cornerstoneTools.addTool(cornerstoneTools.CrosshairsTool)
|
||||||
|
|
@ -864,7 +998,7 @@ export default {
|
||||||
}
|
}
|
||||||
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
|
||||||
mouseButtonMask: 1,
|
mouseButtonMask: 1,
|
||||||
synchronizationContext: synchronizer
|
synchronizationContext: synchronizer,
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
disabledViewPortToolSync(synchronizer, toolName) {
|
disabledViewPortToolSync(synchronizer, toolName) {
|
||||||
|
|
@ -1095,7 +1229,7 @@ export default {
|
||||||
'CobbAngle',
|
'CobbAngle',
|
||||||
'Angle',
|
'Angle',
|
||||||
'Bidirectional',
|
'Bidirectional',
|
||||||
'FreehandRoi'
|
'FreehandRoi',
|
||||||
]
|
]
|
||||||
for (let i = 0; i < toolROITypes.length; i++) {
|
for (let i = 0; i < toolROITypes.length; i++) {
|
||||||
const toolROIType = toolROITypes[i]
|
const toolROIType = toolROITypes[i]
|
||||||
|
|
@ -1115,12 +1249,12 @@ export default {
|
||||||
removeLabel(item) {
|
removeLabel(item) {
|
||||||
const promise = scroll(this.canvas, item.data.imageIdIndex)
|
const promise = scroll(this.canvas, item.data.imageIdIndex)
|
||||||
const scope = this
|
const scope = this
|
||||||
Promise.all([promise]).then(res => {
|
Promise.all([promise]).then((res) => {
|
||||||
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
|
cornerstoneTools.removeToolState(scope.canvas, item.type, item.data)
|
||||||
cornerstone.updateImage(scope.canvas)
|
cornerstone.updateImage(scope.canvas)
|
||||||
})
|
})
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,105 +6,68 @@
|
||||||
<dicom-canvas ref="dicomCanvas" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
</div>-->
|
</div>-->
|
||||||
|
<div class="Anonymous" v-if="isAnonymous">
|
||||||
<div v-show="layoutRow>=1" class="dicom-row" :style="{height: rowHeight}">
|
<div :class="{ btn: true, activeBtn: activeTool === 'Note_RectangleRoi' }"
|
||||||
<div
|
@click="setToolActive($event, 'Note_RectangleRoi')">矩形</div>
|
||||||
v-show="layoutRow>=1&&layoutCol>=1"
|
<div :class="{ btn: true, activeBtn: activeTool === 'Eraser' }" @click="setToolActive($event, 'Eraser')">清除
|
||||||
class="dicom-item"
|
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas0'}"
|
|
||||||
data-index="0"
|
|
||||||
@click="activateDicomCanvas(0)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas
|
|
||||||
ref="dicomCanvas0"
|
|
||||||
style="width:100%;height:100%"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="btn" @click="anonymousImage">应用</div>
|
||||||
v-show="layoutRow>=1&&layoutCol>=2"
|
<div class="btn">应用整个序列</div>
|
||||||
class="dicom-item"
|
<!-- <div class="btn">刷新图像</div> -->
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas1'}"
|
<div class="btn" v-if="!isComparison">对比</div>
|
||||||
data-index="1"
|
<div class="btn" v-else>退出</div>
|
||||||
@click="activateDicomCanvas(1)"
|
<div class="btn">恢复</div>
|
||||||
@dblclick="setFullScreen($event)"
|
</div>
|
||||||
>
|
<div v-show="layoutRow >= 1" class="dicom-row" :style="{ height: rowHeight }">
|
||||||
|
<div v-show="layoutRow >= 1 && layoutCol >= 1" class="dicom-item"
|
||||||
|
:class="{ 'activeItem': activeItem == 'dicomCanvas0' }" data-index="0" @click="activateDicomCanvas(0)"
|
||||||
|
@dblclick="setFullScreen($event)">
|
||||||
|
<dicom-canvas ref="dicomCanvas0" style="width:100%;height:100%" />
|
||||||
|
</div>
|
||||||
|
<div v-show="layoutRow >= 1 && layoutCol >= 2" class="dicom-item"
|
||||||
|
:class="{ 'activeItem': activeItem == 'dicomCanvas1' }" data-index="1" @click="activateDicomCanvas(1)"
|
||||||
|
@dblclick="setFullScreen($event)">
|
||||||
<dicom-canvas ref="dicomCanvas1" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas1" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-show="layoutRow >= 1 && layoutCol >= 3" class="dicom-item"
|
||||||
v-show="layoutRow>=1&&layoutCol>=3"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas2' }" data-index="2" @click="activateDicomCanvas(2)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas2'}"
|
|
||||||
data-index="2"
|
|
||||||
@click="activateDicomCanvas(2)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas2" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas2" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="layoutRow >= 2" class="dicom-row" :style="{ height: rowHeight }">
|
<div v-show="layoutRow >= 2" class="dicom-row" :style="{ height: rowHeight }">
|
||||||
<div
|
<div v-show="layoutRow >= 2 && layoutCol >= 1" class="dicom-item"
|
||||||
v-show="layoutRow>=2&&layoutCol>=1"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas3' }" data-index="3" @click="activateDicomCanvas(3)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas3'}"
|
|
||||||
data-index="3"
|
|
||||||
@click="activateDicomCanvas(3)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas3" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas3" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-show="layoutRow >= 2 && layoutCol >= 2" class="dicom-item"
|
||||||
v-show="layoutRow>=2&&layoutCol>=2"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas4' }" data-index="4" @click="activateDicomCanvas(4)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas4'}"
|
|
||||||
data-index="4"
|
|
||||||
@click="activateDicomCanvas(4)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas4" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas4" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-show="layoutRow >= 2 && layoutCol >= 3" class="dicom-item"
|
||||||
v-show="layoutRow>=2&&layoutCol>=3"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas5' }" data-index="5" @click="activateDicomCanvas(5)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas5'}"
|
|
||||||
data-index="5"
|
|
||||||
@click="activateDicomCanvas(5)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas5" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas5" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-show="layoutRow == 3" class="dicom-row" :style="{ height: rowHeight }">
|
<div v-show="layoutRow == 3" class="dicom-row" :style="{ height: rowHeight }">
|
||||||
<div
|
<div v-show="layoutRow == 3 && layoutCol >= 1" class="dicom-item"
|
||||||
v-show="layoutRow==3&&layoutCol>=1"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas6' }" data-index="6" @click="activateDicomCanvas(6)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas6'}"
|
|
||||||
data-index="6"
|
|
||||||
@click="activateDicomCanvas(6)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas6" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas6" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-show="layoutRow == 3 && layoutCol >= 2" class="dicom-item"
|
||||||
v-show="layoutRow==3&&layoutCol>=2"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas7' }" data-index="7" @click="activateDicomCanvas(7)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas7'}"
|
|
||||||
data-index="7"
|
|
||||||
@click="activateDicomCanvas(7)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas7" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas7" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-show="layoutRow == 3 && layoutCol >= 3" class="dicom-item"
|
||||||
v-show="layoutRow==3&&layoutCol>=3"
|
:class="{ 'activeItem': activeItem == 'dicomCanvas8' }" data-index="8" @click="activateDicomCanvas(8)"
|
||||||
class="dicom-item"
|
@dblclick="setFullScreen($event)">
|
||||||
:class="{'activeItem':activeItem=='dicomCanvas8'}"
|
|
||||||
data-index="8"
|
|
||||||
@click="activateDicomCanvas(8)"
|
|
||||||
@dblclick="setFullScreen($event)"
|
|
||||||
>
|
|
||||||
<dicom-canvas ref="dicomCanvas8" style="width:100%;height:100%" />
|
<dicom-canvas ref="dicomCanvas8" style="width:100%;height:100%" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -116,7 +79,7 @@
|
||||||
<div class="sideTool-title">{{ $t('trials:reading:button:layout') }}</div>
|
<div class="sideTool-title">{{ $t('trials:reading:button:layout') }}</div>
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<label>{{ $t('trials:reading:button:layout') }}:</label>
|
<label>{{ $t('trials:reading:button:layout') }}:</label>
|
||||||
<select class="sidetool-select" style="width:90px" @change="changeLayout($event)">
|
<select class="sidetool-select" style="width:90px" :disabled="isAnonymous" @change="changeLayout($event)">
|
||||||
<option value="1x1" selected>1x1</option>
|
<option value="1x1" selected>1x1</option>
|
||||||
<option value="1x2">1x2</option>
|
<option value="1x2">1x2</option>
|
||||||
<option value="2x1">2x1</option>
|
<option value="2x1">2x1</option>
|
||||||
|
|
@ -127,18 +90,15 @@
|
||||||
<option value="3x2">3x2</option>
|
<option value="3x2">3x2</option>
|
||||||
<option value="3x3">3x3</option>
|
<option value="3x3">3x3</option>
|
||||||
</select>
|
</select>
|
||||||
|
<div class="btnBox" @click="openAnonymous">像素匿名</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 图像变换 -->
|
<!-- 图像变换 -->
|
||||||
<div class="measureTool-wrapper">
|
<div class="measureTool-wrapper">
|
||||||
<div class="sideTool-title">{{ $t('trials:dicom-show:transform') }}</div>
|
<div class="sideTool-title">{{ $t('trials:dicom-show:transform') }}</div>
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<button
|
<button :title="$t('trials:reading:button:wwwc')" class="btn-link" data-tool="Wwwc"
|
||||||
:title="$t('trials:reading:button:wwwc')"
|
@click="setToolActive($event, 'Wwwc')">
|
||||||
class="btn-link"
|
|
||||||
data-tool="Wwwc"
|
|
||||||
@click="setToolActive($event,'Wwwc')"
|
|
||||||
>
|
|
||||||
<svg-icon icon-class="reverse" style="font-size:20px;" />
|
<svg-icon icon-class="reverse" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- <button
|
<!-- <button
|
||||||
|
|
@ -149,17 +109,15 @@
|
||||||
>
|
>
|
||||||
<svg-icon icon-class="wwwcRegion" style="font-size:20px;" />
|
<svg-icon icon-class="wwwcRegion" style="font-size:20px;" />
|
||||||
</button>-->
|
</button>-->
|
||||||
<button
|
<button :title="$t('trials:reading:button:reverseColor')" class="btn-link" @click="toggleInvert">
|
||||||
:title="$t('trials:reading:button:reverseColor')"
|
|
||||||
class="btn-link"
|
|
||||||
@click="toggleInvert"
|
|
||||||
>
|
|
||||||
<svg-icon icon-class="reversecolor" style="font-size:20px;" />
|
<svg-icon icon-class="reversecolor" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<button :title="$t('trials:reading:button:zoom')" class="btn-link" data-tool="Zoom" @click="setToolActive($event,'Zoom')">
|
<button :title="$t('trials:reading:button:zoom')" class="btn-link" data-tool="Zoom"
|
||||||
|
@click="setToolActive($event, 'Zoom')">
|
||||||
<svg-icon icon-class="magnifier" style="font-size:20px;" />
|
<svg-icon icon-class="magnifier" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<button :title="$t('trials:dicom-show:lens')" class="btn-link" data-tool="Magnify" @click="setToolActive($event,'Magnify')">
|
<button :title="$t('trials:dicom-show:lens')" class="btn-link" data-tool="Magnify"
|
||||||
|
@click="setToolActive($event, 'Magnify')">
|
||||||
<svg-icon icon-class="zoom" style="font-size:20px;" />
|
<svg-icon icon-class="zoom" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
|
<button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
|
||||||
|
|
@ -172,17 +130,19 @@
|
||||||
<div @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</div>
|
<div @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</div>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<button :title="$t('trials:reading:button:move')" class="btn-link" data-tool="Pan" @click="setToolActive($event,'Pan')">
|
<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;" />
|
<svg-icon icon-class="move" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<button :title="$t('trials:reading:button:fitWindow')" class="btn-link" data-tool="fitToWindow" @click="fitToType($event,'fitToWindow')">
|
<button :title="$t('trials:reading:button:fitWindow')" class="btn-link" data-tool="fitToWindow"
|
||||||
|
@click="fitToType($event, 'fitToWindow')">
|
||||||
<svg-icon icon-class="fitToWindow" style="font-size:20px;" />
|
<svg-icon icon-class="fitToWindow" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<button :title="$t('trials:reading:button:fitImage')" class="btn-link" data-tool="fitToImage" @click="fitToType($event,'fitToImage')">
|
<button :title="$t('trials:reading:button:fitImage')" class="btn-link" data-tool="fitToImage"
|
||||||
|
@click="fitToType($event, 'fitToImage')">
|
||||||
<svg-icon icon-class="fitToImage" style="font-size:20px;" />
|
<svg-icon icon-class="fitToImage" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> -->
|
<!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> -->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 测量标注 -->
|
<!-- 测量标注 -->
|
||||||
|
|
@ -190,43 +150,53 @@
|
||||||
<div class="sideTool-title">{{ $t('trials:dicom-show:measurementLabeling') }}</div>
|
<div class="sideTool-title">{{ $t('trials:dicom-show:measurementLabeling') }}</div>
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<!-- 探针 -->
|
<!-- 探针 -->
|
||||||
<button :title="$t('trials:dicom-show:Probe')" class="btn-link" data-tool="Probe" @click="setToolActive($event,'Probe')">
|
<button :title="$t('trials:dicom-show:Probe')" class="btn-link" data-tool="Probe"
|
||||||
|
@click="setToolActive($event, 'Probe')">
|
||||||
<svg-icon icon-class="pixel" style="font-size:20px;" />
|
<svg-icon icon-class="pixel" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 长度测量 -->
|
<!-- 长度测量 -->
|
||||||
<button :title="$t('trials:dicom-show:Length')" class="btn-link" data-tool="Length" @click="setToolActive($event,'Length')">
|
<button :title="$t('trials:dicom-show:Length')" class="btn-link" data-tool="Length"
|
||||||
|
@click="setToolActive($event, 'Length')">
|
||||||
<svg-icon icon-class="length" style="font-size:20px;" />
|
<svg-icon icon-class="length" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 角度测量 -->
|
<!-- 角度测量 -->
|
||||||
<button :title="$t('trials:dicom-show:Angle')" class="btn-link" data-tool="Angle" @click="setToolActive($event,'Angle')">
|
<button :title="$t('trials:dicom-show:Angle')" class="btn-link" data-tool="Angle"
|
||||||
|
@click="setToolActive($event, 'Angle')">
|
||||||
<svg-icon icon-class="angle" style="font-size:20px;" />
|
<svg-icon icon-class="angle" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- Cobb测量 -->
|
<!-- Cobb测量 -->
|
||||||
<button :title="$t('trials:dicom-show:CobbAngle')" class="btn-link" data-tool="CobbAngle" @click="setToolActive($event,'CobbAngle')">
|
<button :title="$t('trials:dicom-show:CobbAngle')" class="btn-link" data-tool="CobbAngle"
|
||||||
|
@click="setToolActive($event, 'CobbAngle')">
|
||||||
<svg-icon icon-class="cobb" style="font-size:20px;" />
|
<svg-icon icon-class="cobb" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 椭圆测量 -->
|
<!-- 椭圆测量 -->
|
||||||
<button :title="$t('trials:dicom-show:EllipticalRoi')" class="btn-link" data-tool="EllipticalRoi" @click="setToolActive($event,'EllipticalRoi')">
|
<button :title="$t('trials:dicom-show:EllipticalRoi')" class="btn-link" data-tool="EllipticalRoi"
|
||||||
|
@click="setToolActive($event, 'EllipticalRoi')">
|
||||||
<svg-icon icon-class="oval" style="font-size:20px;" />
|
<svg-icon icon-class="oval" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 矩形测量 -->
|
<!-- 矩形测量 -->
|
||||||
<button :title="$t('trials:dicom-show:RectangleRoi')" class="btn-link" data-tool="RectangleRoi" @click="setToolActive($event,'RectangleRoi')">
|
<button :title="$t('trials:dicom-show:RectangleRoi')" class="btn-link" data-tool="RectangleRoi"
|
||||||
|
@click="setToolActive($event, 'RectangleRoi')">
|
||||||
<svg-icon icon-class="rectangle" style="font-size:20px;" />
|
<svg-icon icon-class="rectangle" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 多边形标记 -->
|
<!-- 多边形标记 -->
|
||||||
<button :title="$t('trials:dicom-show:FreehandRoi')" class="btn-link" data-tool="FreehandRoi" @click="setToolActive($event,'FreehandRoi')">
|
<button :title="$t('trials:dicom-show:FreehandRoi')" class="btn-link" data-tool="FreehandRoi"
|
||||||
|
@click="setToolActive($event, 'FreehandRoi')">
|
||||||
<svg-icon icon-class="polygon" style="font-size:20px;" />
|
<svg-icon icon-class="polygon" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 十字线 -->
|
<!-- 十字线 -->
|
||||||
<button :title="$t('trials:dicom-show:Bidirectional')" class="btn-link" data-tool="Bidirectional" @click="setToolActive($event,'Bidirectional')">
|
<button :title="$t('trials:dicom-show:Bidirectional')" class="btn-link" data-tool="Bidirectional"
|
||||||
|
@click="setToolActive($event, 'Bidirectional')">
|
||||||
<svg-icon icon-class="bidirection" style="font-size:20px;" />
|
<svg-icon icon-class="bidirection" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 文字标注 -->
|
<!-- 文字标注 -->
|
||||||
<button :title="$t('trials:dicom-show:ArrowAnnotate')" class="btn-link" data-tool="ArrowAnnotate" @click="setToolActive($event,'ArrowAnnotate')">
|
<button :title="$t('trials:dicom-show:ArrowAnnotate')" class="btn-link" data-tool="ArrowAnnotate"
|
||||||
|
@click="setToolActive($event, 'ArrowAnnotate')">
|
||||||
<svg-icon icon-class="label" style="font-size:20px;" />
|
<svg-icon icon-class="label" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 清除测量和标记 -->
|
<!-- 清除测量和标记 -->
|
||||||
<button :title="$t('trials:dicom-show:Eraser')" class="btn-link" data-tool="Eraser" @click="setToolActive($event,'Eraser')">
|
<button :title="$t('trials:dicom-show:Eraser')" class="btn-link" data-tool="Eraser"
|
||||||
|
@click="setToolActive($event, 'Eraser')">
|
||||||
<svg-icon icon-class="clear" style="font-size:20px;" />
|
<svg-icon icon-class="clear" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 截屏 -->
|
<!-- 截屏 -->
|
||||||
|
|
@ -244,26 +214,27 @@
|
||||||
<div class="sideTool-title">{{ $t('trials:dicom-show:play') }}</div>
|
<div class="sideTool-title">{{ $t('trials:dicom-show:play') }}</div>
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<!-- 第一帧 -->
|
<!-- 第一帧 -->
|
||||||
<button class="btn-link" :title="$t('trials:dicom-show:firstframe')" @click="currentDicomCanvas.scrollPage(-9999)">
|
<button class="btn-link" :title="$t('trials:dicom-show:firstframe')"
|
||||||
|
@click="currentDicomCanvas.scrollPage(-9999)">
|
||||||
<svg-icon icon-class="firstframe" style="font-size:20px;" />
|
<svg-icon icon-class="firstframe" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 显示上一张影像 -->
|
<!-- 显示上一张影像 -->
|
||||||
<button class="btn-link" :title="$t('trials:dicom-show:previousframe')" @click="currentDicomCanvas.scrollPage(-1)">
|
<button class="btn-link" :title="$t('trials:dicom-show:previousframe')"
|
||||||
|
@click="currentDicomCanvas.scrollPage(-1)">
|
||||||
<svg-icon icon-class="previousframe" style="font-size:20px;" />
|
<svg-icon icon-class="previousframe" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 播放 -->
|
<!-- 播放 -->
|
||||||
<button class="btn-link" :title="$t('trials:dicom-show:play')" @click="clipPlay">
|
<button class="btn-link" :title="$t('trials:dicom-show:play')" @click="clipPlay">
|
||||||
<svg-icon
|
<svg-icon :icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'"
|
||||||
:icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'"
|
style="font-size:20px;" />
|
||||||
style="font-size:20px;"
|
|
||||||
/>
|
|
||||||
</button>
|
</button>
|
||||||
<!-- 下一帧 -->
|
<!-- 下一帧 -->
|
||||||
<button class="btn-link" :title="$t('trials:dicom-show:nextframe')" @click="currentDicomCanvas.scrollPage(1)">
|
<button class="btn-link" :title="$t('trials:dicom-show:nextframe')" @click="currentDicomCanvas.scrollPage(1)">
|
||||||
<svg-icon icon-class="nextframe" style="font-size:20px;" />
|
<svg-icon icon-class="nextframe" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<!-- 最后一帧 -->
|
<!-- 最后一帧 -->
|
||||||
<button class="btn-link" :title="$t('trials:dicom-show:lastframe')" @click="currentDicomCanvas.scrollPage(9999)">
|
<button class="btn-link" :title="$t('trials:dicom-show:lastframe')"
|
||||||
|
@click="currentDicomCanvas.scrollPage(9999)">
|
||||||
<svg-icon icon-class="lastframe" style="font-size:20px;" />
|
<svg-icon icon-class="lastframe" style="font-size:20px;" />
|
||||||
</button>
|
</button>
|
||||||
<select v-model="fps" class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)">
|
<select v-model="fps" class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)">
|
||||||
|
|
@ -282,163 +253,91 @@
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<!-- 预设窗位值 -->
|
<!-- 预设窗位值 -->
|
||||||
<label>{{ $t('trials:dicom-show:dicomCanvasWwwc') }}:</label>
|
<label>{{ $t('trials:dicom-show:dicomCanvasWwwc') }}:</label>
|
||||||
<select
|
<select v-model="wwwcList[currentDicomCanvasIndex]" class="sidetool-select" style="width:100px"
|
||||||
v-model="wwwcList[currentDicomCanvasIndex]"
|
@change="setDicomCanvasWwwc($event)">
|
||||||
class="sidetool-select"
|
|
||||||
style="width:100px"
|
|
||||||
@change="setDicomCanvasWwwc($event)"
|
|
||||||
>
|
|
||||||
<!-- 默认值 -->
|
<!-- 默认值 -->
|
||||||
<option :value="-1">{{ $t('trials:dicom-show:default') }}</option>
|
<option :value="-1">{{ $t('trials:dicom-show:default') }}</option>
|
||||||
<!-- 自定义 -->
|
<!-- 自定义 -->
|
||||||
<option :value="0">{{ $t('trials:dicom-show:custom') }}</option>
|
<option :value="0">{{ $t('trials:dicom-show:custom') }}</option>
|
||||||
<!-- 区域窗宽 -->
|
<!-- 区域窗宽 -->
|
||||||
<option :value="1" style="border-bottom:1px solid #fff;">{{ $t('trials:reading:button:wwwcRegion') }}</option>
|
<option :value="1" style="border-bottom:1px solid #fff;">{{ $t('trials:reading:button:wwwcRegion') }}
|
||||||
<option :value="2">
|
|
||||||
CT Abdomen
|
|
||||||
</option>
|
|
||||||
<option :value="3">
|
|
||||||
CT Angio
|
|
||||||
</option>
|
|
||||||
<option :value="4">
|
|
||||||
CT Bone
|
|
||||||
</option>
|
|
||||||
<option :value="5">
|
|
||||||
CT Brain
|
|
||||||
</option>
|
|
||||||
<option :value="6">
|
|
||||||
CT Chest
|
|
||||||
</option>
|
|
||||||
<option :value="7">
|
|
||||||
CT Lungs
|
|
||||||
</option>
|
</option>
|
||||||
|
<option :value="2">CT Abdomen</option>
|
||||||
|
<option :value="3">CT Angio</option>
|
||||||
|
<option :value="4">CT Bone</option>
|
||||||
|
<option :value="5">CT Brain</option>
|
||||||
|
<option :value="6">CT Chest</option>
|
||||||
|
<option :value="7">CT Lungs</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<!-- 伪彩色 -->
|
<!-- 伪彩色 -->
|
||||||
<label>{{ $t('trials:dicom-show:pseudocolor') }}:</label>
|
<label>{{ $t('trials:dicom-show:pseudocolor') }}:</label>
|
||||||
<select
|
<select v-model="colorList[currentDicomCanvasIndex]" class="sidetool-select" style="width:90px"
|
||||||
v-model="colorList[currentDicomCanvasIndex]"
|
@change="setColormap($event)">
|
||||||
class="sidetool-select"
|
|
||||||
style="width:90px"
|
|
||||||
@change="setColormap($event)"
|
|
||||||
>
|
|
||||||
<!-- 默认值 -->
|
<!-- 默认值 -->
|
||||||
<option value>{{ $t('trials:dicom-show:default') }}</option>
|
<option value>{{ $t('trials:dicom-show:default') }}</option>
|
||||||
<option
|
<option v-for="(item, index) in colormapsList" :key="index" :value="item.id">{{ item.name }}</option>
|
||||||
v-for="(item,index) in colormapsList"
|
|
||||||
:key="index"
|
|
||||||
:value="item.id"
|
|
||||||
>{{ item.name }}</option>
|
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 患者信息 -->
|
<!-- 患者信息 -->
|
||||||
<div class="measureTool-wrapper patient-form" v-if="isHaveStudyClinicalData && type === 'Study' && modality && ['PT、CT', 'CT、PT', 'PET-CT'].includes(modality)">
|
<div class="measureTool-wrapper patient-form"
|
||||||
|
v-if="isHaveStudyClinicalData && type === 'Study' && modality && ['PT、CT', 'CT、PT', 'PET-CT'].includes(modality)">
|
||||||
<div class="sideTool-title">{{ $t('trials:tab:patientData') }}</div>
|
<div class="sideTool-title">{{ $t('trials:tab:patientData') }}</div>
|
||||||
<div class="sideTool-wrapper">
|
<div class="sideTool-wrapper">
|
||||||
<el-form
|
<el-form ref="patientForm" :model="formData" :rules="rules" label-width="150" v-loading="formLoading">
|
||||||
ref="patientForm"
|
|
||||||
:model="formData"
|
|
||||||
:rules="rules"
|
|
||||||
label-width="150"
|
|
||||||
v-loading="formLoading"
|
|
||||||
>
|
|
||||||
<!-- 性别 -->
|
<!-- 性别 -->
|
||||||
<el-form-item :label="$t('trials:ptData:label:patientSex')" prop="PatientSex">
|
<el-form-item :label="$t('trials:ptData:label:patientSex')" prop="PatientSex">
|
||||||
<el-select
|
<el-select v-model="formData.PatientSex" :placeholder="$t('common:ruleMessage:select')"
|
||||||
v-model="formData.PatientSex"
|
style="width: 100%" size="small" :disabled="!isEdit">
|
||||||
:placeholder="$t('common:ruleMessage:select')"
|
|
||||||
style="width: 100%"
|
|
||||||
size="small"
|
|
||||||
:disabled="!isEdit"
|
|
||||||
>
|
|
||||||
<el-option :label="$t('trials:patientSex:male')" value="M"></el-option>
|
<el-option :label="$t('trials:patientSex:male')" value="M"></el-option>
|
||||||
<el-option :label="$t('trials:patientSex:female')" value="F"></el-option>
|
<el-option :label="$t('trials:patientSex:female')" value="F"></el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 体重(kg) 例如 70.5-->
|
<!-- 体重(kg) 例如 70.5-->
|
||||||
<el-form-item :label="$t('trials:ptData:label:patientWeight')" prop="PatientWeight">
|
<el-form-item :label="$t('trials:ptData:label:patientWeight')" prop="PatientWeight">
|
||||||
<el-input
|
<el-input v-model.number="formData.PatientWeight" :placeholder="$t('trials:patientWeight:eg')"
|
||||||
v-model.number="formData.PatientWeight"
|
style="width: 100%" size="small" :disabled="!isEdit"></el-input>
|
||||||
:placeholder="$t('trials:patientWeight:eg')"
|
|
||||||
style="width: 100%"
|
|
||||||
size="small"
|
|
||||||
:disabled="!isEdit"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 总剂量(Bq) 例如 740000000-->
|
<!-- 总剂量(Bq) 例如 740000000-->
|
||||||
<el-form-item :label="$t('trials:ptData:label:totalDose')" prop="RadionuclideTotalDose">
|
<el-form-item :label="$t('trials:ptData:label:totalDose')" prop="RadionuclideTotalDose">
|
||||||
<el-input
|
<el-input v-model.number="formData.RadionuclideTotalDose" :placeholder="$t('trials:totalDose:eg')"
|
||||||
v-model.number="formData.RadionuclideTotalDose"
|
style="width: 100%" size="small" :disabled="!isEdit"></el-input>
|
||||||
:placeholder="$t('trials:totalDose:eg')"
|
|
||||||
style="width: 100%"
|
|
||||||
size="small"
|
|
||||||
:disabled="!isEdit"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 半衰期(s) 例如 21600-->
|
<!-- 半衰期(s) 例如 21600-->
|
||||||
<el-form-item :label="$t('trials:ptData:label:halfLife')" prop="RadionuclideHalfLife">
|
<el-form-item :label="$t('trials:ptData:label:halfLife')" prop="RadionuclideHalfLife">
|
||||||
<el-input
|
<el-input v-model.number="formData.RadionuclideHalfLife" :placeholder="$t('trials:halfLife:eg')"
|
||||||
v-model.number="formData.RadionuclideHalfLife"
|
style="width: 100%" size="small" :disabled="!isEdit"></el-input>
|
||||||
:placeholder="$t('trials:halfLife:eg')"
|
|
||||||
style="width: 100%"
|
|
||||||
size="small"
|
|
||||||
:disabled="!isEdit"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 注射时间(s) Unix 秒 或 相对秒-->
|
<!-- 注射时间(s) Unix 秒 或 相对秒-->
|
||||||
<el-form-item :label="$t('trials:ptData:label:injectTime')" prop="RadiopharmaceuticalStartTime">
|
<el-form-item :label="$t('trials:ptData:label:injectTime')" prop="RadiopharmaceuticalStartTime">
|
||||||
<el-input
|
<el-input v-model.number="formData.RadiopharmaceuticalStartTime" :placeholder="$t('trials:injectTime:eg')"
|
||||||
v-model.number="formData.RadiopharmaceuticalStartTime"
|
style="width: 100%" @input="computeTimeRelation" size="small" :disabled="!isEdit"></el-input>
|
||||||
:placeholder="$t('trials:injectTime:eg')"
|
|
||||||
style="width: 100%"
|
|
||||||
@input="computeTimeRelation"
|
|
||||||
size="small"
|
|
||||||
:disabled="!isEdit"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 成像时间(s) Unix 秒 或 相对秒-->
|
<!-- 成像时间(s) Unix 秒 或 相对秒-->
|
||||||
<el-form-item :label="$t('trials:ptData:label:acquisitionTime')" prop="AcquisitionTime">
|
<el-form-item :label="$t('trials:ptData:label:acquisitionTime')" prop="AcquisitionTime">
|
||||||
<el-input
|
<el-input v-model.number="formData.AcquisitionTime" :placeholder="$t('trials:injectTime:eg')"
|
||||||
v-model.number="formData.AcquisitionTime"
|
style="width: 100%" @input="computeTimeRelation" size="small" :disabled="!isEdit"></el-input>
|
||||||
:placeholder="$t('trials:injectTime:eg')"
|
|
||||||
style="width: 100%"
|
|
||||||
@input="computeTimeRelation"
|
|
||||||
size="small"
|
|
||||||
:disabled="!isEdit"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 时间一致性检查 -->
|
<!-- 时间一致性检查 -->
|
||||||
<el-form-item :label="$t('trials:ptData:label:timeCheck')">
|
<el-form-item :label="$t('trials:ptData:label:timeCheck')">
|
||||||
<el-input
|
<el-input v-model="formData.TimeCheck" disabled style="width: 100%" size="small"></el-input>
|
||||||
v-model="formData.TimeCheck"
|
|
||||||
disabled
|
|
||||||
style="width: 100%"
|
|
||||||
size="small"
|
|
||||||
></el-input>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 提交 -->
|
<!-- 提交 -->
|
||||||
<el-form-item style="margin-top: 20px;text-align: right;" v-if="isEdit">
|
<el-form-item style="margin-top: 20px;text-align: right;" v-if="isEdit">
|
||||||
<el-button type="primary" @click="submitForm" size="small">{{ $t('trials:ptData:button:submit') }}</el-button>
|
<el-button type="primary" @click="submitForm" size="small">{{ $t('trials:ptData:button:submit')
|
||||||
|
}}</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<el-dialog
|
<el-dialog v-if="customWwc.visible" :visible.sync="customWwc.visible" :close-on-click-modal="false"
|
||||||
v-if="customWwc.visible"
|
:title="customWwc.title" width="400px" custom-class="base-dialog-wrapper" append-to-body>
|
||||||
:visible.sync="customWwc.visible"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:title="customWwc.title"
|
|
||||||
width="400px"
|
|
||||||
custom-class="base-dialog-wrapper"
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<CustomWwwcForm @close="customWwc.visible = false" @setWwwc="setWwwc" />
|
<CustomWwwcForm @close="customWwc.visible = false" @setWwwc="setWwwc" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -456,7 +355,10 @@ import Hammer from 'hammerjs'
|
||||||
cornerstoneTools.external.cornerstone = cornerstone
|
cornerstoneTools.external.cornerstone = cornerstone
|
||||||
cornerstoneTools.external.Hammer = Hammer
|
cornerstoneTools.external.Hammer = Hammer
|
||||||
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
cornerstoneTools.external.cornerstoneMath = cornerstoneMath
|
||||||
|
console.log(cornerstoneTools, 'cornerstoneTools')
|
||||||
|
console.log(cornerstone, 'cornerstone')
|
||||||
import '@/utils/dialog'
|
import '@/utils/dialog'
|
||||||
|
import { studyMaskImage, studyUndoMaskImage } from "@/api/reading"
|
||||||
import {
|
import {
|
||||||
getPatientInfo,
|
getPatientInfo,
|
||||||
editPatientInfo
|
editPatientInfo
|
||||||
|
|
@ -465,9 +367,13 @@ export default {
|
||||||
name: 'DicomsViewer',
|
name: 'DicomsViewer',
|
||||||
components: {
|
components: {
|
||||||
DicomCanvas,
|
DicomCanvas,
|
||||||
CustomWwwcForm
|
CustomWwwcForm,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
|
loading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
modality: {
|
modality: {
|
||||||
type: String,
|
type: String,
|
||||||
default: ''
|
default: ''
|
||||||
|
|
@ -475,6 +381,8 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
isAnonymous: false,
|
||||||
|
isComparison: false,
|
||||||
activeTool: '',
|
activeTool: '',
|
||||||
activeItem: 'dicomCanvas0',
|
activeItem: 'dicomCanvas0',
|
||||||
layoutRow: 1,
|
layoutRow: 1,
|
||||||
|
|
@ -482,12 +390,12 @@ export default {
|
||||||
currentDicomCanvasIndex: 0,
|
currentDicomCanvasIndex: 0,
|
||||||
currentDicomCanvas: {
|
currentDicomCanvas: {
|
||||||
toolState: {
|
toolState: {
|
||||||
clipPlaying: false
|
clipPlaying: false,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
rowHeight: '100%',
|
rowHeight: '100%',
|
||||||
sync: {
|
sync: {
|
||||||
Wwwc: null
|
Wwwc: null,
|
||||||
},
|
},
|
||||||
colormapsList: [],
|
colormapsList: [],
|
||||||
rotateList: [],
|
rotateList: [],
|
||||||
|
|
@ -495,6 +403,7 @@ export default {
|
||||||
wwwcList: [],
|
wwwcList: [],
|
||||||
layout: null,
|
layout: null,
|
||||||
seriesList: [],
|
seriesList: [],
|
||||||
|
series: {},
|
||||||
customWwc: { visible: false, title: null },
|
customWwc: { visible: false, title: null },
|
||||||
fps: 15,
|
fps: 15,
|
||||||
formData: {
|
formData: {
|
||||||
|
|
@ -541,7 +450,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.customWwc = { visible: false, title: this.$t('DicomViewer:data:customWwc') }
|
this.customWwc = {
|
||||||
|
visible: false,
|
||||||
|
title: this.$t('DicomViewer:data:customWwc'),
|
||||||
|
}
|
||||||
this.rotateList[0] = '1'
|
this.rotateList[0] = '1'
|
||||||
this.colorList[0] = ''
|
this.colorList[0] = ''
|
||||||
this.wwwcList[0] = '-1'
|
this.wwwcList[0] = '-1'
|
||||||
|
|
@ -556,11 +468,83 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
|
anonymousImage() {
|
||||||
|
console.log(this.series, 'this.series')
|
||||||
|
this.$refs[`dicomCanvas0`].getNote_RectangleRoi().then(async obj => {
|
||||||
|
let { toolInfo, image } = obj
|
||||||
|
console.log(image, 'image')
|
||||||
|
if (!toolInfo || toolInfo.data.length <= 0) return this.$confirm(this.$t("DicomViewer:anonymous:notMark"))
|
||||||
|
let instanceInfo = this.series.instanceInfoList.find(item => item.ImageId === image.imageId)
|
||||||
|
let data = {
|
||||||
|
// SeriesId: this.series.seriesId,
|
||||||
|
instanceIdList: [instanceInfo.Id],
|
||||||
|
MaskRegionList: []
|
||||||
|
}
|
||||||
|
toolInfo.data.forEach(item => {
|
||||||
|
let currentStart = item.handles.start
|
||||||
|
let currentEnd = item.handles.end
|
||||||
|
let start = {
|
||||||
|
x: currentStart.x > currentEnd.x ? Math.round(currentEnd.x) : Math.round(currentStart.x),
|
||||||
|
y: currentStart.y > currentEnd.y ? Math.round(currentEnd.y) : Math.round(currentStart.y),
|
||||||
|
}
|
||||||
|
let end = {
|
||||||
|
x: currentStart.x > currentEnd.x ? Math.round(currentStart.x) : Math.round(currentEnd.x),
|
||||||
|
y: currentStart.y > currentEnd.y ? Math.round(currentStart.y) : Math.round(currentEnd.y),
|
||||||
|
}
|
||||||
|
let width = end.x - start.x
|
||||||
|
let height = end.y - start.y
|
||||||
|
data.MaskRegionList.push({
|
||||||
|
X: start.x,
|
||||||
|
Y: start.y,
|
||||||
|
Width: width,
|
||||||
|
Height: height
|
||||||
|
})
|
||||||
|
})
|
||||||
|
let res = await this.studyMaskImage(data)
|
||||||
|
if (!res) return false
|
||||||
|
// this.$emit("update:loading", true)
|
||||||
|
// let strs = image.imageId.split("?")
|
||||||
|
// let newImageId = `${strs[0]}-MaskImage?${strs[1]}`
|
||||||
|
// console.log(newImageId, 'newImageId')
|
||||||
|
// this.$refs[`dicomCanvas0`].reloadImage(newImageId)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
openAnonymous() {
|
||||||
|
this.isAnonymous = !this.isAnonymous
|
||||||
|
if (!this.isAnonymous) {
|
||||||
|
const elements = document.querySelectorAll('.dicom-item')
|
||||||
|
const scope = this
|
||||||
|
scope.activeTool = null
|
||||||
|
Array.from(elements).forEach((element, index) => {
|
||||||
|
if (element.style.display !== 'none') {
|
||||||
|
scope.$refs[`dicomCanvas${index}`].setToolPassive(toolName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
this.activateDicomCanvas(0)
|
||||||
|
this.changeLayout('1x1')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async studyMaskImage(data) {
|
||||||
|
try {
|
||||||
|
this.$emit("update:loading", true)
|
||||||
|
let res = await studyMaskImage(data)
|
||||||
|
this.$emit("update:loading", false)
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
this.$emit("update:loading", false)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
},
|
||||||
loadImageStack(dicomSeries) {
|
loadImageStack(dicomSeries) {
|
||||||
this.currentDicomCanvas.toolState.clipPlaying = false
|
this.currentDicomCanvas.toolState.clipPlaying = false
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
const series = Object.assign({}, dicomSeries)
|
this.series = Object.assign({}, dicomSeries)
|
||||||
this.currentDicomCanvas.loadImageStack(series)
|
this.currentDicomCanvas.loadImageStack(this.series)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
loadOtherImageStack(seriesList) {
|
loadOtherImageStack(seriesList) {
|
||||||
|
|
@ -609,7 +593,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeLayout(event) {
|
changeLayout(event) {
|
||||||
const arr = event.target.value.split('x')
|
const arr = event.target ? event.target.value.split('x') : event.split('x')
|
||||||
this.layoutRow = parseInt(arr[0])
|
this.layoutRow = parseInt(arr[0])
|
||||||
this.layoutCol = parseInt(arr[1])
|
this.layoutCol = parseInt(arr[1])
|
||||||
this.rowHeight = 100 / this.layoutRow + '%'
|
this.rowHeight = 100 / this.layoutRow + '%'
|
||||||
|
|
@ -646,11 +630,21 @@ export default {
|
||||||
cornerstone.resize(e.currentTarget.children[0])
|
cornerstone.resize(e.currentTarget.children[0])
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
fillColor() {
|
||||||
|
const elements = document.querySelectorAll('.dicom-item')
|
||||||
|
const scope = this
|
||||||
|
Array.from(elements).forEach((element, index) => {
|
||||||
|
if (element.style.display !== 'none') {
|
||||||
|
scope.$refs[`dicomCanvas${index}`].fillColor()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
setToolActive(e, toolName) {
|
setToolActive(e, toolName) {
|
||||||
const elements = document.querySelectorAll('.dicom-item')
|
const elements = document.querySelectorAll('.dicom-item')
|
||||||
if (e.currentTarget.classList.contains('activeTool')) {
|
if (e.currentTarget.classList.contains('activeTool')) {
|
||||||
e.currentTarget.classList.remove('activeTool')
|
e.currentTarget.classList.remove('activeTool')
|
||||||
const scope = this
|
const scope = this
|
||||||
|
scope.activeTool = null
|
||||||
Array.from(elements).forEach((element, index) => {
|
Array.from(elements).forEach((element, index) => {
|
||||||
if (element.style.display !== 'none') {
|
if (element.style.display !== 'none') {
|
||||||
scope.$refs[`dicomCanvas${index}`].setToolPassive(toolName)
|
scope.$refs[`dicomCanvas${index}`].setToolPassive(toolName)
|
||||||
|
|
@ -664,6 +658,7 @@ export default {
|
||||||
e.currentTarget.classList.add('activeTool')
|
e.currentTarget.classList.add('activeTool')
|
||||||
|
|
||||||
const scope = this
|
const scope = this
|
||||||
|
scope.activeTool = toolName
|
||||||
Array.from(elements).forEach((element, index) => {
|
Array.from(elements).forEach((element, index) => {
|
||||||
if (element.style.display !== 'none') {
|
if (element.style.display !== 'none') {
|
||||||
scope.$refs[`dicomCanvas${index}`].setToolActive(toolName)
|
scope.$refs[`dicomCanvas${index}`].setToolActive(toolName)
|
||||||
|
|
@ -864,11 +859,11 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
||||||
.dicom-wrapper {
|
.dicom-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .case-dialog-class {
|
.dicom-wrapper .case-dialog-class {
|
||||||
position: fixed;
|
position: fixed;
|
||||||
left: 25%;
|
left: 25%;
|
||||||
|
|
@ -879,30 +874,85 @@ export default {
|
||||||
|
|
||||||
.dicom-wrapper .case-dialog-div {
|
.dicom-wrapper .case-dialog-div {
|
||||||
pointer-events: none;
|
pointer-events: none;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .case-dialog-class .el-dialog__body {
|
.dicom-wrapper .case-dialog-class .el-dialog__body {
|
||||||
max-height: 300px;
|
max-height: 300px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .el-dialog__header {
|
.dicom-wrapper .el-dialog__header {
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .el-dialog__body {
|
.dicom-wrapper .el-dialog__body {
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-viewer {
|
.dicom-viewer {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.Anonymous {
|
||||||
|
position: absolute;
|
||||||
|
border-radius: 5px;
|
||||||
|
bottom: 30px;
|
||||||
|
left: 5%;
|
||||||
|
right: 5%;
|
||||||
|
width: 90%;
|
||||||
|
height: 60px;
|
||||||
|
padding: 0 10px;
|
||||||
|
background-color: rgba(255, 255, 255, .2);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
z-index: 9999;
|
||||||
|
|
||||||
|
.btn {
|
||||||
|
width: 15%;
|
||||||
|
text-align: center;
|
||||||
|
height: 40px;
|
||||||
|
line-height: 30px;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: rgba(255, 255, 255, .3);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, .7);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba(255, 255, 255, .5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.activeBtn {
|
||||||
|
background-color: rgba(255, 255, 255, .5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.btnBox {
|
||||||
|
display: inline-block;
|
||||||
|
width: 80px;
|
||||||
|
text-align: center;
|
||||||
|
height: 30px;
|
||||||
|
line-height: 20px;
|
||||||
|
border-radius: 15px;
|
||||||
|
background-color: rgba(255, 255, 255, .3);
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border: 1px solid rgba(255, 255, 255, .7);
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dicom-row {
|
.dicom-wrapper .dicom-row {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dicom-item {
|
.dicom-wrapper .dicom-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
width: 0;
|
width: 0;
|
||||||
|
|
@ -912,9 +962,11 @@ export default {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
border: 1px solid #c8c8c8;
|
border: 1px solid #c8c8c8;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .activeItem {
|
.dicom-wrapper .activeItem {
|
||||||
border: 2px solid chocolate;
|
border: 2px solid chocolate;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-item-fullscreen {
|
.dicom-item-fullscreen {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
@ -923,14 +975,17 @@ export default {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
z-index: 1;
|
z-index: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper ::-webkit-scrollbar {
|
.dicom-wrapper ::-webkit-scrollbar {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper ::-webkit-scrollbar-thumb {
|
.dicom-wrapper ::-webkit-scrollbar-thumb {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: gray;
|
background: gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dicom-tools {
|
.dicom-wrapper .dicom-tools {
|
||||||
/* display: flex;
|
/* display: flex;
|
||||||
flex-direction: column; */
|
flex-direction: column; */
|
||||||
|
|
@ -945,26 +1000,30 @@ export default {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .measure-wrapper {
|
.dicom-wrapper .measure-wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.measure-wrapper .measure-list {
|
.measure-wrapper .measure-list {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.measure-list-header {
|
.measure-list-header {
|
||||||
padding: 2px 0px;
|
padding: 2px 0px;
|
||||||
border-bottom: 1px solid gray;
|
border-bottom: 1px solid gray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.measure-wrapper ul {
|
.measure-wrapper ul {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.measure-wrapper ul li {
|
.measure-wrapper ul li {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -981,9 +1040,11 @@ export default {
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
color: #606626;
|
color: #606626;
|
||||||
}
|
}
|
||||||
|
|
||||||
.measure-wrapper select>option {
|
.measure-wrapper select>option {
|
||||||
color: #323232;
|
color: #323232;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* .measure-wrapper select {
|
/* .measure-wrapper select {
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
|
|
@ -1003,6 +1064,7 @@ export default {
|
||||||
.dicom-canvas.active {
|
.dicom-canvas.active {
|
||||||
border: 1px solid #337ab7;
|
border: 1px solid #337ab7;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sideTool-title {
|
.sideTool-title {
|
||||||
padding: 5px 8px;
|
padding: 5px 8px;
|
||||||
background-color: #525252;
|
background-color: #525252;
|
||||||
|
|
@ -1010,30 +1072,36 @@ export default {
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
margin: 4px;
|
margin: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sideTool-wrapper {
|
.sideTool-wrapper {
|
||||||
border-bottom: 1px solid gray;
|
border-bottom: 1px solid gray;
|
||||||
margin: 0px 4px;
|
margin: 0px 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sideTool-wrapper .btn {
|
.sideTool-wrapper .btn {
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidetool-select {
|
.sidetool-select {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
background-color: rgba(0, 0, 0, 0);
|
background-color: rgba(0, 0, 0, 0);
|
||||||
color: #d0d0d0;
|
color: #d0d0d0;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidetool-select>option {
|
.sidetool-select>option {
|
||||||
background-color: #323232;
|
background-color: #323232;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sideTool-wrapper button.btn-link {
|
.sideTool-wrapper button.btn-link {
|
||||||
height: 40px;
|
height: 40px;
|
||||||
padding: 8px !important;
|
padding: 8px !important;
|
||||||
border: 1px solid rgba(37, 37, 37, 1);
|
border: 1px solid rgba(37, 37, 37, 1);
|
||||||
margin: 1px 1px;
|
margin: 1px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sideTool-wrapper .btn-link {
|
.sideTool-wrapper .btn-link {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
|
@ -1041,6 +1109,7 @@ export default {
|
||||||
border: 1px solid rgba(37, 37, 37, 1);
|
border: 1px solid rgba(37, 37, 37, 1);
|
||||||
margin: 1px 1px;
|
margin: 1px 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .btn-group {
|
.dicom-wrapper .btn-group {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
|
@ -1057,6 +1126,7 @@ export default {
|
||||||
border: 1px solid rgba(37, 37, 37, 1);
|
border: 1px solid rgba(37, 37, 37, 1);
|
||||||
min-height: 30px;
|
min-height: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .btn-group .btn-left {
|
.dicom-wrapper .btn-group .btn-left {
|
||||||
position: relative;
|
position: relative;
|
||||||
float: left;
|
float: left;
|
||||||
|
|
@ -1065,20 +1135,23 @@ export default {
|
||||||
border-bottom-right-radius: 0;
|
border-bottom-right-radius: 0;
|
||||||
border-top-right-radius: 0;
|
border-top-right-radius: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .activeTool {
|
.dicom-wrapper .activeTool {
|
||||||
background: #16477b90 !important;
|
background: #16477b90 !important;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .btn-link {
|
.dicom-wrapper .btn-link {
|
||||||
color: #cccccc;
|
color: #cccccc;
|
||||||
background-color: #ffffff00;
|
background-color: #ffffff00;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .btn-submit {
|
.dicom-wrapper .btn-submit {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
/* background-color: #eeeeee; */
|
/* background-color: #eeeeee; */
|
||||||
background: #eeeeee;
|
background: #eeeeee;
|
||||||
border: 1px solid #DCDFE6;
|
border: 1px solid #dcdfe6;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
@ -1093,10 +1166,12 @@ export default {
|
||||||
.dicom-wrapper .iconHover:hover {
|
.dicom-wrapper .iconHover:hover {
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dropdown {
|
.dicom-wrapper .dropdown {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dropdown-content {
|
.dicom-wrapper .dropdown-content {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
@ -1109,14 +1184,17 @@ export default {
|
||||||
border: 1px solid #4e4e4e;
|
border: 1px solid #4e4e4e;
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dropdown:hover .dropdown-content {
|
.dicom-wrapper .dropdown:hover .dropdown-content {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dropdown-content div {
|
.dicom-wrapper .dropdown-content div {
|
||||||
height: 25px;
|
height: 25px;
|
||||||
line-height: 25px;
|
line-height: 25px;
|
||||||
cursor: point;
|
cursor: point;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dicom-wrapper .dropdown-content div:hover {
|
.dicom-wrapper .dropdown-content div:hover {
|
||||||
background-color: #16477b90;
|
background-color: #16477b90;
|
||||||
}
|
}
|
||||||
|
|
@ -1124,15 +1202,17 @@ export default {
|
||||||
.patient-form .el-form-item {
|
.patient-form .el-form-item {
|
||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.patient-form .el-form-item__label {
|
.patient-form .el-form-item__label {
|
||||||
color: #d0d0d0;
|
color: #d0d0d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.patient-form .el-input.is-disabled .el-input__inner {
|
.patient-form .el-input.is-disabled .el-input__inner {
|
||||||
background-color: #424244;
|
background-color: #424244;
|
||||||
}
|
}
|
||||||
|
|
||||||
.patient-form .el-input .el-input__inner {
|
.patient-form .el-input .el-input__inner {
|
||||||
background-color: #323232;
|
background-color: #323232;
|
||||||
color: #d0d0d0;
|
color: #d0d0d0;
|
||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -123,7 +123,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="viewerContent">
|
<div class="viewerContent">
|
||||||
<dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" :modality="modality"/>
|
<dicom-viewer id="dicomViewer" ref="dicomViewer" style="height:100%" :loading.sync="loading"
|
||||||
|
:modality="modality" />
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="viewerRightSidePanel">
|
<!-- <div class="viewerRightSidePanel">
|
||||||
<dicom-tools />
|
<dicom-tools />
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
// Note_RectangleRoiTool.js
|
||||||
|
import * as cornerstoneTools from 'cornerstone-tools';
|
||||||
|
|
||||||
|
export default class Note_RectangleRoiTool extends cornerstoneTools.RectangleRoiTool {
|
||||||
|
constructor(props = {}) {
|
||||||
|
const defaultProps = {
|
||||||
|
name: 'Note_RectangleRoi',
|
||||||
|
configuration: {
|
||||||
|
fillColor: 'rgba(255, 255, 0, 0.3)', // 默认填充颜色:半透明黄色
|
||||||
|
strokeColor: 'yellow', // 边框颜色
|
||||||
|
lineWidth: 2, // 边框宽度
|
||||||
|
drawHandles: true, // 是否绘制控制点
|
||||||
|
handleColor: 'white', // 控制点颜色
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super({ ...defaultProps, ...props });
|
||||||
|
}
|
||||||
|
|
||||||
|
renderToolData(evt) {
|
||||||
|
const eventData = evt.detail;
|
||||||
|
const { element } = eventData;
|
||||||
|
|
||||||
|
// 获取工具状态
|
||||||
|
const toolData = cornerstoneTools.getToolState(element, this.name);
|
||||||
|
|
||||||
|
if (!toolData || !toolData.data || !toolData.data.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const canvas = eventData.canvasContext.canvas;
|
||||||
|
const context = canvas.getContext('2d');
|
||||||
|
|
||||||
|
context.save();
|
||||||
|
|
||||||
|
// 获取配置
|
||||||
|
const fillColor = this.configuration.fillColor || 'rgba(255, 255, 0, 0.3)';
|
||||||
|
const strokeColor = this.configuration.strokeColor || 'yellow';
|
||||||
|
const lineWidth = this.configuration.lineWidth || 2;
|
||||||
|
const drawHandles = this.configuration.drawHandles !== false;
|
||||||
|
|
||||||
|
// 遍历所有矩形标注
|
||||||
|
toolData.data.forEach((measurement) => {
|
||||||
|
if (!measurement.handles?.start || !measurement.handles?.end) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const start = measurement.handles.start;
|
||||||
|
const end = measurement.handles.end;
|
||||||
|
|
||||||
|
// 计算矩形坐标和尺寸
|
||||||
|
const x = Math.min(start.x, end.x);
|
||||||
|
const y = Math.min(start.y, end.y);
|
||||||
|
const width = Math.abs(end.x - start.x);
|
||||||
|
const height = Math.abs(end.y - start.y);
|
||||||
|
|
||||||
|
// 1. 绘制填充
|
||||||
|
if (fillColor) {
|
||||||
|
context.fillStyle = fillColor;
|
||||||
|
context.fillRect(x, y, width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. 绘制边框
|
||||||
|
context.strokeStyle = strokeColor;
|
||||||
|
context.lineWidth = lineWidth;
|
||||||
|
context.strokeRect(x, y, width, height);
|
||||||
|
|
||||||
|
// 3. 绘制控制点(可选)
|
||||||
|
if (drawHandles) {
|
||||||
|
this.drawHandles(context, measurement, eventData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
context.restore();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 绘制控制点
|
||||||
|
*/
|
||||||
|
drawHandles(context, measurement, eventData) {
|
||||||
|
const handles = measurement.handles;
|
||||||
|
const handleColor = this.configuration.handleColor || 'white';
|
||||||
|
|
||||||
|
// 绘制所有控制点
|
||||||
|
Object.keys(handles).forEach(key => {
|
||||||
|
const handle = handles[key];
|
||||||
|
if (handle && typeof handle.x === 'number' && typeof handle.y === 'number') {
|
||||||
|
context.beginPath();
|
||||||
|
context.arc(handle.x, handle.y, 5, 0, 2 * Math.PI);
|
||||||
|
context.fillStyle = handleColor;
|
||||||
|
context.fill();
|
||||||
|
context.strokeStyle = 'black';
|
||||||
|
context.lineWidth = 1;
|
||||||
|
context.stroke();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue