Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
commit
e7562fbe83
|
|
@ -0,0 +1 @@
|
||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1782284218093" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4982" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M512 51.2a460.8 460.8 0 1 1 0 921.6 460.8 460.8 0 0 1 0-921.6z m0 51.2a409.6 409.6 0 1 0 0 819.2 409.6 409.6 0 0 0 0-819.2z" fill="#ffffff" p-id="4983"></path><path d="M512 358.4c70.4 0 137.1136 5.2736 196.7616 14.6432l27.0336 4.6592C877.1584 403.9168 972.8 454.2464 972.8 512c0 57.7536-95.6416 108.032-237.0048 134.2976l-27.0336 4.608A1275.1872 1275.1872 0 0 1 512 665.6c-70.4 0-137.1136-5.2736-196.7616-14.6432l-27.0336-4.6592C146.8416 620.0832 51.2 569.7536 51.2 512c0-57.7536 95.6416-108.032 237.0048-134.2976l27.0336-4.608c55.0912-8.704 116.1728-13.824 180.5824-14.592L512 358.4z m0 51.2c-31.5904 0-62.3104 1.1776-91.8528 3.328l-29.0816 2.5088-28.2112 3.072c-23.1424 2.7648-45.2096 6.144-66.048 9.984l-24.4224 4.7616-23.0912 5.12-21.76 5.5296C150.3744 464.5376 102.4 490.8544 102.4 512c0 21.1456 47.9744 47.4624 125.1328 68.096l21.76 5.4784 23.0912 5.1712 24.4224 4.7616c20.8384 3.84 42.9056 7.168 66.048 9.984l28.16 3.072 29.1328 2.5088a1261.4656 1261.4656 0 0 0 183.7056 0l29.0816-2.5088 28.2112-3.072c23.1424-2.7648 45.2096-6.144 66.048-9.984l24.4224-4.7616 23.0912-5.12 21.76-5.5296C873.6256 559.4624 921.6 533.1456 921.6 512c0-21.1456-47.9744-47.4624-125.1328-68.096l-21.76-5.4784-23.0912-5.1712-24.4224-4.7616c-20.8384-3.84-42.9056-7.168-66.048-9.984l-28.16-3.072-29.1328-2.5088c-24.576-1.792-50.0736-2.9184-76.1344-3.2256L512 409.6z" fill="#ffffff" p-id="4984"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.7 KiB |
|
|
@ -121,7 +121,7 @@ const actions = {
|
||||||
localStorage.setItem('CompanyInfo', JSON.stringify(response.Result.CompanyInfo))
|
localStorage.setItem('CompanyInfo', JSON.stringify(response.Result.CompanyInfo))
|
||||||
const data = response.Result
|
const data = response.Result
|
||||||
commit('SET_ROLES', data.BasicInfo.AccountList)
|
commit('SET_ROLES', data.BasicInfo.AccountList)
|
||||||
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1) {
|
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1 || data.BasicInfo.IsNeedResetPwd) {
|
||||||
try {
|
try {
|
||||||
zzSessionStorage.setItem('userId', data.BasicInfo.Id)
|
zzSessionStorage.setItem('userId', data.BasicInfo.Id)
|
||||||
commit('SET_TOKEN', data.JWTStr)
|
commit('SET_TOKEN', data.JWTStr)
|
||||||
|
|
|
||||||
|
|
@ -156,7 +156,7 @@
|
||||||
<!-- {{ $t('login:title:system_title_about') }} -->
|
<!-- {{ $t('login:title:system_title_about') }} -->
|
||||||
<img src="@/assets/system.png" alt=""
|
<img src="@/assets/system.png" alt=""
|
||||||
:style="{ width: isEN ? '180px' : '200px', height: isEN ? '60px' : '65px' }" />
|
:style="{ width: isEN ? '180px' : '200px', height: isEN ? '60px' : '65px' }" />
|
||||||
<p style="margin-bottom: 0px">{{ $t('login:title:system') }}</p>
|
<p style="margin-bottom: 0px">{{ $t('login:title:system') }}</p>
|
||||||
</div>
|
</div>
|
||||||
<p style="margin-bottom: 20px; margin-top: 0">
|
<p style="margin-bottom: 20px; margin-top: 0">
|
||||||
V{{ $version.IsEnv_US ? $version.Version_US : $version.Version }}
|
V{{ $version.IsEnv_US ? $version.Version_US : $version.Version }}
|
||||||
|
|
@ -374,6 +374,15 @@ export default {
|
||||||
})
|
})
|
||||||
}, 500)
|
}, 500)
|
||||||
return
|
return
|
||||||
|
} else if (res.BasicInfo.IsNeedResetPwd) {
|
||||||
|
// 当前用户管理员重置密码,请先修改密码之后再次登录
|
||||||
|
this.$message.success(this.$t('login:message:login5'))
|
||||||
|
setTimeout(() => {
|
||||||
|
this.$router.push({
|
||||||
|
path: `/user-recompose?UserId=${res.BasicInfo.IdentityUserId}&Email=${res.BasicInfo.EMail}&UserName=${res.BasicInfo.UserName}&lang=${this.$i18n.locale}&access_token=${res.JWTStr}&isUpdate=1`,
|
||||||
|
})
|
||||||
|
}, 500)
|
||||||
|
return
|
||||||
} else if (res.BasicInfo.NeedChangePassWord) {
|
} else if (res.BasicInfo.NeedChangePassWord) {
|
||||||
// 请先修改密码后再登录!
|
// 请先修改密码后再登录!
|
||||||
this.$alert(
|
this.$alert(
|
||||||
|
|
|
||||||
|
|
@ -3076,6 +3076,8 @@ export default {
|
||||||
}
|
}
|
||||||
} else if (this.activeTool === FusionJumpToPointTool.toolName) {
|
} else if (this.activeTool === FusionJumpToPointTool.toolName) {
|
||||||
this.setFusionMipJumpEnabled(false)
|
this.setFusionMipJumpEnabled(false)
|
||||||
|
} else if (this.activeTool === 'SphericalBrush') {
|
||||||
|
toolGroup.setToolDisabled('ThresholdSphere')
|
||||||
} else {
|
} else {
|
||||||
toolGroup.setToolPassive(this.activeTool)
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@
|
||||||
<div :title="$t('trials:Segmentations:tools:thresholecircle')"
|
<div :title="$t('trials:Segmentations:tools:thresholecircle')"
|
||||||
:class="['tool-item', ThresholdTools.includes(activeTool) && segmentList.length > 0 ? 'tool-item-active' : '']"
|
:class="['tool-item', ThresholdTools.includes(activeTool) && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
@click.prevent="initThreshold">
|
@click.prevent="initThreshold()">
|
||||||
<svg-icon icon-class="thresholecircle" class="svg-icon" />
|
<svg-icon icon-class="thresholecircle" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div :title="$t('trials:Segmentations:tools:circularbrush')"
|
<div :title="$t('trials:Segmentations:tools:circularbrush')"
|
||||||
|
|
@ -28,6 +28,12 @@
|
||||||
@click.prevent="setToolActive('CircularBrush')">
|
@click.prevent="setToolActive('CircularBrush')">
|
||||||
<svg-icon icon-class="circularbrush" class="svg-icon" />
|
<svg-icon icon-class="circularbrush" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
|
<div :title="$t('trials:Segmentations:tools:SphericalBrush')"
|
||||||
|
:class="['tool-item', activeTool === 'SphericalBrush' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
|
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
|
@click.prevent="initThreshold('SphericalBrush')">
|
||||||
|
<svg-icon icon-class="sphericalBrush" class="svg-icon" />
|
||||||
|
</div>
|
||||||
<div :class="['tool-item', activeTool === 'CircularEraser' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
<div :class="['tool-item', activeTool === 'CircularEraser' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: isMPR || segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
:title="$t('trials:Segmentations:tools:Eraser')"
|
:title="$t('trials:Segmentations:tools:Eraser')"
|
||||||
|
|
@ -40,7 +46,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ConfigBox">
|
<div class="ConfigBox">
|
||||||
<div class="EraserConfig"
|
<div class="EraserConfig"
|
||||||
v-if="activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
v-if="activeTool === 'SphericalBrush' || activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
||||||
<span>{{ $t('trials:reading:Segmentations:title:EraserConfigSection') }}</span>
|
<span>{{ $t('trials:reading:Segmentations:title:EraserConfigSection') }}</span>
|
||||||
<el-select v-model="sliderMax" placeholder="" size="small" @change="handleSliderChange">
|
<el-select v-model="sliderMax" placeholder="" size="small" @change="handleSliderChange">
|
||||||
<el-option v-for="item in sliderSection" :key="item.id" :label="item.label"
|
<el-option v-for="item in sliderSection" :key="item.id" :label="item.label"
|
||||||
|
|
@ -48,8 +54,8 @@
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="EraserConfig"
|
<div class="EraserConfig RadiusConfig"
|
||||||
v-if="activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
v-if="activeTool === 'SphericalBrush' || activeTool === 'CircularEraser' || activeTool === 'CircularBrush' || ThresholdTools.includes(activeTool)">
|
||||||
<span>{{ $t('trials:reading:Segmentations:title:EraserConfig') }}</span>
|
<span>{{ $t('trials:reading:Segmentations:title:EraserConfig') }}</span>
|
||||||
<el-slider v-model="brushSize" show-input :step="sliderStep" :max="sliderMax" input-size="mini"
|
<el-slider v-model="brushSize" show-input :step="sliderStep" :max="sliderMax" input-size="mini"
|
||||||
:show-input-controls="false" />
|
:show-input-controls="false" />
|
||||||
|
|
@ -656,8 +662,13 @@ export default {
|
||||||
handleClickPopover(item) {
|
handleClickPopover(item) {
|
||||||
this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}`
|
this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}`
|
||||||
},
|
},
|
||||||
initThreshold() {
|
initThreshold(key = null) {
|
||||||
if (this.isMPR) return false
|
if (this.isMPR) return false
|
||||||
|
if (key === 'SphericalBrush') {
|
||||||
|
this.setToolActive(this.ThresholdTools[1], 'SphericalBrush')
|
||||||
|
this.setSphericalBrushConfig()
|
||||||
|
return false
|
||||||
|
}
|
||||||
if (!this.ThresholdTools.includes(this.activeTool)) {
|
if (!this.ThresholdTools.includes(this.activeTool)) {
|
||||||
this.setToolActive(this.ThresholdTools[0])
|
this.setToolActive(this.ThresholdTools[0])
|
||||||
this.thresholdType = this.ThresholdTools[0]
|
this.thresholdType = this.ThresholdTools[0]
|
||||||
|
|
@ -777,7 +788,7 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
setToolActive(toolName) {
|
setToolActive(toolName, name = null) {
|
||||||
if (this.segmentList.length <= 0) return false
|
if (this.segmentList.length <= 0) return false
|
||||||
if (this.curSegment.lock) return false
|
if (this.curSegment.lock) return false
|
||||||
if (this.isMPR) return false
|
if (this.isMPR) return false
|
||||||
|
|
@ -806,10 +817,15 @@ export default {
|
||||||
// if (toolName === 'CircularEraser') {
|
// if (toolName === 'CircularEraser') {
|
||||||
// console.log(toolGroup.getToolInstance(toolName))
|
// console.log(toolGroup.getToolInstance(toolName))
|
||||||
// }
|
// }
|
||||||
this.$emit('update:activeTool', toolName)
|
if (name) {
|
||||||
this.setBrushSize(toolName)
|
this.$emit('update:activeTool', name)
|
||||||
if (this.ThresholdTools.includes(toolName)) {
|
this.setBrushSize(name)
|
||||||
this.setBrushThreshold()
|
} else {
|
||||||
|
this.$emit('update:activeTool', toolName)
|
||||||
|
this.setBrushSize(toolName)
|
||||||
|
if (this.ThresholdTools.includes(toolName)) {
|
||||||
|
this.setBrushThreshold()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -1516,6 +1532,21 @@ export default {
|
||||||
if (toolName === 'ThresholdSphere') {
|
if (toolName === 'ThresholdSphere') {
|
||||||
this.setDynamicRadius()
|
this.setDynamicRadius()
|
||||||
}
|
}
|
||||||
|
if (toolName === 'SphericalBrush') {
|
||||||
|
this.setSphericalBrushConfig()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setSphericalBrushConfig() {
|
||||||
|
let volume = cache.getVolume(this.series.SeriesInstanceUid);
|
||||||
|
let { spacing, numFrames } = volume
|
||||||
|
let constant = numFrames * spacing[2] / 100
|
||||||
|
let dynamicRadius = Math.ceil(this.brushSize * constant)
|
||||||
|
let obj = {
|
||||||
|
dynamicRadius: dynamicRadius,
|
||||||
|
isDynamic: false,
|
||||||
|
range: [-10000, 100000]
|
||||||
|
}
|
||||||
|
this.setBrushThreshold(obj)
|
||||||
},
|
},
|
||||||
setDynamicRadius() {
|
setDynamicRadius() {
|
||||||
let volume = cache.getVolume(this.series.SeriesInstanceUid);
|
let volume = cache.getVolume(this.series.SeriesInstanceUid);
|
||||||
|
|
@ -1523,7 +1554,7 @@ export default {
|
||||||
let constant = numFrames * spacing[2] / 100
|
let constant = numFrames * spacing[2] / 100
|
||||||
this.brushThreshold.dynamicRadius = Math.ceil(this.brushSize * constant)
|
this.brushThreshold.dynamicRadius = Math.ceil(this.brushSize * constant)
|
||||||
},
|
},
|
||||||
setBrushThreshold() {
|
setBrushThreshold(OBJ = null) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
let brushThreshold = {
|
let brushThreshold = {
|
||||||
isDynamic: this.brushThreshold.isDynamic,
|
isDynamic: this.brushThreshold.isDynamic,
|
||||||
|
|
@ -1532,6 +1563,7 @@ export default {
|
||||||
if (!this.brushThreshold.isDynamic) {
|
if (!this.brushThreshold.isDynamic) {
|
||||||
brushThreshold.range = this.brushThreshold.range
|
brushThreshold.range = this.brushThreshold.range
|
||||||
}
|
}
|
||||||
|
if (OBJ) brushThreshold = OBJ
|
||||||
CStUtils.segmentation.setBrushThresholdForToolGroup(toolGroupId, brushThreshold);
|
CStUtils.segmentation.setBrushThresholdForToolGroup(toolGroupId, brushThreshold);
|
||||||
},
|
},
|
||||||
async createSegmentation(segmentationId) {
|
async createSegmentation(segmentationId) {
|
||||||
|
|
@ -1566,7 +1598,7 @@ export default {
|
||||||
},
|
},
|
||||||
segmentationModifiedCallback(evt) {
|
segmentationModifiedCallback(evt) {
|
||||||
const { detail } = evt;
|
const { detail } = evt;
|
||||||
let tools = [...this.ThresholdTools, ...this.tools]
|
let tools = [...this.ThresholdTools, ...this.tools, 'SphericalBrush']
|
||||||
if (!detail || detail.segmentIndex === 255 || !this.activeTool || !tools.includes(this.activeTool)) {
|
if (!detail || detail.segmentIndex === 255 || !this.activeTool || !tools.includes(this.activeTool)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -1584,12 +1616,26 @@ export default {
|
||||||
console.log(stats)
|
console.log(stats)
|
||||||
if (mode === 'individual') {
|
if (mode === 'individual') {
|
||||||
const segmentStats = stats;
|
const segmentStats = stats;
|
||||||
|
|
||||||
for (const segmentIndex of indices) {
|
for (const segmentIndex of indices) {
|
||||||
if (segmentStats[segmentIndex]) {
|
if (segmentStats[segmentIndex]) {
|
||||||
const segmentStat = segmentStats[segmentIndex];
|
const segmentStat = segmentStats[segmentIndex];
|
||||||
// console.log(segmentStat, 'segmentStat')
|
// console.log(segmentStat, 'segmentStat')
|
||||||
segmentStat.count.label = 'Voxels';
|
segmentStat.count.label = 'Voxels';
|
||||||
|
if (this.series.Modality === 'PT') {
|
||||||
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
|
const viewport = renderingEngine.getViewport(viewportId);
|
||||||
|
let imageIds = viewport.getImageIds(this.series.SeriesInstanceUid)
|
||||||
|
let imageId = imageIds[0]
|
||||||
|
const suvFactor = metaData.get('scalingModule', imageId) || {};
|
||||||
|
console.log(suvFactor, 'suvFactor')
|
||||||
|
segmentStat.sulpeak = {
|
||||||
|
label: "Mean Pixel",
|
||||||
|
name: "sulpeak",
|
||||||
|
unit: "SUL",
|
||||||
|
value: suvFactor.suvlbm && suvFactor.suvbw ? segmentStat.mean.value * suvFactor.suvlbm / suvFactor.suvbw : 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId)
|
let segmentGroup = this.segmentList.find(item => item.segmentationId === segmentationId)
|
||||||
if (segmentGroup) {
|
if (segmentGroup) {
|
||||||
let segment = segmentGroup.segments.find(item => item.segmentIndex === segmentIndex)
|
let segment = segmentGroup.segments.find(item => item.segmentIndex === segmentIndex)
|
||||||
|
|
@ -1617,12 +1663,12 @@ export default {
|
||||||
contentMouseup() {
|
contentMouseup() {
|
||||||
try {
|
try {
|
||||||
// console.log("segment contentMouseup")
|
// console.log("segment contentMouseup")
|
||||||
if (!this.drawing) return false
|
|
||||||
if (this.timeoutId) {
|
if (this.timeoutId) {
|
||||||
clearTimeout(this.timeoutId);
|
clearTimeout(this.timeoutId);
|
||||||
this.timeoutId = null;
|
this.timeoutId = null;
|
||||||
}
|
}
|
||||||
this.timeoutId = setTimeout(() => {
|
this.timeoutId = setTimeout(() => {
|
||||||
|
if (!this.drawing) return false
|
||||||
this.timeoutId = null;
|
this.timeoutId = null;
|
||||||
this.drawing = false;
|
this.drawing = false;
|
||||||
let segmentGroup = this.segmentList.find(item => item.segmentationId === this.segmentationId)
|
let segmentGroup = this.segmentList.find(item => item.segmentationId === this.segmentationId)
|
||||||
|
|
@ -2498,6 +2544,21 @@ export default {
|
||||||
.EraserConfig {
|
.EraserConfig {
|
||||||
margin: 5px 0;
|
margin: 5px 0;
|
||||||
|
|
||||||
|
::v-deep .el-input-number {
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-input-number.is-without-controls .el-input__inner {
|
||||||
|
padding: 0 10px;
|
||||||
|
width: 90px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::v-deep .el-radio-button__inner {
|
||||||
|
width: 105px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.RadiusConfig {
|
||||||
::v-deep .el-input-number {
|
::v-deep .el-input-number {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -409,7 +409,7 @@ const config = {
|
||||||
'name': 'Labelmap分割',
|
'name': 'Labelmap分割',
|
||||||
'icon': 'labelmap',
|
'icon': 'labelmap',
|
||||||
'toolName': 'Labelmap',
|
'toolName': 'Labelmap',
|
||||||
'props': ['max', 'min', 'volume', 'count', 'mean', 'stdDev', 'length', 'width'],
|
'props': ['max', 'min', 'volume', 'count', 'mean', 'stdDev', 'length', 'width', 'sulpeak'],
|
||||||
'i18nKey': 'trials:reading:button:Labelmap',
|
'i18nKey': 'trials:reading:button:Labelmap',
|
||||||
'isDisabled': false,
|
'isDisabled': false,
|
||||||
'disabledReason': ''
|
'disabledReason': ''
|
||||||
|
|
|
||||||
|
|
@ -32,13 +32,8 @@
|
||||||
<svg-icon icon-class="rotate" class="svg-icon" />
|
<svg-icon icon-class="rotate" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 查看关键序列 -->
|
<!-- 查看关键序列 -->
|
||||||
<el-popover
|
<el-popover v-model="keySeriesPopoverVisible" placement="bottom" trigger="click"
|
||||||
v-model="keySeriesPopoverVisible"
|
popper-class="key-series-popper" @show="showKeySeriesPanel">
|
||||||
placement="bottom"
|
|
||||||
trigger="click"
|
|
||||||
popper-class="key-series-popper"
|
|
||||||
@show="showKeySeriesPanel"
|
|
||||||
>
|
|
||||||
<ul class="key-series-list">
|
<ul class="key-series-list">
|
||||||
<li v-if="keyTaskInfo && keyTaskInfo.TaskBlindName" class="key-series-header">
|
<li v-if="keyTaskInfo && keyTaskInfo.TaskBlindName" class="key-series-header">
|
||||||
<div class="key-series-header-top">
|
<div class="key-series-header-top">
|
||||||
|
|
@ -56,12 +51,8 @@
|
||||||
<li v-else-if="keySeries.length === 0" class="key-series-empty">
|
<li v-else-if="keySeries.length === 0" class="key-series-empty">
|
||||||
{{ $t('trials:reading:keyImage:noData') }}
|
{{ $t('trials:reading:keyImage:noData') }}
|
||||||
</li>
|
</li>
|
||||||
<li
|
<li v-for="(kf, idx) in keySeries" :key="idx" class="key-series-item"
|
||||||
v-for="(kf, idx) in keySeries"
|
@click.stop.prevent="jumpToKeySeries(kf)">
|
||||||
:key="idx"
|
|
||||||
class="key-series-item"
|
|
||||||
@click.stop.prevent="jumpToKeySeries(kf)"
|
|
||||||
>
|
|
||||||
<div class="key-series-img">
|
<div class="key-series-img">
|
||||||
<img v-if="kf.PicturePath" :src="`${OSSclientConfig.basePath}${kf.PicturePath}`" />
|
<img v-if="kf.PicturePath" :src="`${OSSclientConfig.basePath}${kf.PicturePath}`" />
|
||||||
<svg-icon v-else icon-class="image" class="svg-icon default-icon" />
|
<svg-icon v-else icon-class="image" class="svg-icon default-icon" />
|
||||||
|
|
@ -117,13 +108,9 @@
|
||||||
:title="$t('trials:nondicom-show:scale')" @click.prevent="setAnnotateToolActive('Lengthscale')">
|
:title="$t('trials:nondicom-show:scale')" @click.prevent="setAnnotateToolActive('Lengthscale')">
|
||||||
<svg-icon icon-class="lengthscale" class="svg-icon" />
|
<svg-icon icon-class="lengthscale" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 截图 -->
|
<!-- 截图 -->
|
||||||
<div
|
<div class="tool-item" :title="$t('trials:reading:button:screenShot')" @click.prevent="saveImage">
|
||||||
class="tool-item"
|
|
||||||
:title="$t('trials:reading:button:screenShot')"
|
|
||||||
@click.prevent="saveImage"
|
|
||||||
>
|
|
||||||
<svg-icon icon-class="image" class="svg-icon" />
|
<svg-icon icon-class="image" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 重置 -->
|
<!-- 重置 -->
|
||||||
|
|
@ -131,8 +118,8 @@
|
||||||
<svg-icon icon-class="refresh" class="svg-icon" />
|
<svg-icon icon-class="refresh" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<!-- 更多:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '']" -->
|
<!-- 更多:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '']" -->
|
||||||
<div v-if="criterionType === 0" :title="$t('trials:reading:button:more')" :class="['tool-item']"
|
<div v-if="criterionType === 0 && customizeStandardsNoneDicom.length > 0" :title="$t('trials:reading:button:more')"
|
||||||
@click.stop="showPanel($event)" @mouseleave="toolMouseout">
|
:class="['tool-item']" @click.stop="showPanel($event)" @mouseleave="toolMouseout">
|
||||||
<div class="dropdown">
|
<div class="dropdown">
|
||||||
<div class="icon" data-tool="more">
|
<div class="icon" data-tool="more">
|
||||||
<svg-icon icon-class="more" class="svg-icon" />
|
<svg-icon icon-class="more" class="svg-icon" />
|
||||||
|
|
@ -310,8 +297,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="content-main" :ref="`video-content-main-${index}`" style="flex: 1;">
|
<div class="content-main" :ref="`video-content-main-${index}`" style="flex: 1;">
|
||||||
<video v-if="v.currentFilePath" :ref="`videovideo-${index}`"
|
<video v-if="v.currentFilePath" :ref="`videovideo-${index}`"
|
||||||
:src="`${OSSclientConfig.basePath}${v.currentFilePath}`" crossorigin="anonymous"
|
:src="`${OSSclientConfig.basePath}${v.currentFilePath}`" crossorigin="anonymous" width="100%"
|
||||||
width="100%" height="100%" autoplay controls controlsList="nodownload"></video>
|
height="100%" autoplay controls controlsList="nodownload"></video>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -349,7 +336,7 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<!-- 其他 -->
|
<!-- 其他 -->
|
||||||
<el-tab-pane :label="$t('trials:reading:tab:others')" name="2">
|
<el-tab-pane :label="$t('trials:reading:tab:others')" name="2">
|
||||||
<Others v-if="activeName === '2'" :imageToolType="2"/>
|
<Others v-if="activeName === '2'" :imageToolType="2" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
@ -1448,7 +1435,7 @@ export default {
|
||||||
this.saveCustomAnnotationTimer = null
|
this.saveCustomAnnotationTimer = null
|
||||||
}
|
}
|
||||||
this.saveCustomAnnotation(annotation)
|
this.saveCustomAnnotation(annotation)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// if (this.isNumber(operateStateEnum)) {
|
// if (this.isNumber(operateStateEnum)) {
|
||||||
// this.removeAnnotation(annotation)
|
// this.removeAnnotation(annotation)
|
||||||
|
|
@ -1943,7 +1930,7 @@ export default {
|
||||||
if (currentViewport.fileType && currentViewport.fileType.includes('mp4')) {
|
if (currentViewport.fileType && currentViewport.fileType.includes('mp4')) {
|
||||||
divForDownloadViewport = this.$refs[`grid-cell-${this.activeCanvasIndex}`][0]
|
divForDownloadViewport = this.$refs[`grid-cell-${this.activeCanvasIndex}`][0]
|
||||||
const videoEl = this.$refs[`videovideo-${this.activeCanvasIndex}`][0]
|
const videoEl = this.$refs[`videovideo-${this.activeCanvasIndex}`][0]
|
||||||
|
|
||||||
if (videoEl) {
|
if (videoEl) {
|
||||||
// 将视频帧画到 canvas 上生成图片
|
// 将视频帧画到 canvas 上生成图片
|
||||||
const tempCanvas = document.createElement('canvas')
|
const tempCanvas = document.createElement('canvas')
|
||||||
|
|
@ -1952,7 +1939,7 @@ export default {
|
||||||
const containerHeight = videoEl.clientHeight
|
const containerHeight = videoEl.clientHeight
|
||||||
tempCanvas.width = containerWidth
|
tempCanvas.width = containerWidth
|
||||||
tempCanvas.height = containerHeight
|
tempCanvas.height = containerHeight
|
||||||
|
|
||||||
const ctx = tempCanvas.getContext('2d')
|
const ctx = tempCanvas.getContext('2d')
|
||||||
// 填充黑色背景
|
// 填充黑色背景
|
||||||
ctx.fillStyle = '#000'
|
ctx.fillStyle = '#000'
|
||||||
|
|
@ -1961,7 +1948,7 @@ export default {
|
||||||
// 计算视频保持比例的缩放尺寸和位置 (等同于 object-fit: contain)
|
// 计算视频保持比例的缩放尺寸和位置 (等同于 object-fit: contain)
|
||||||
const videoWidth = videoEl.videoWidth || containerWidth
|
const videoWidth = videoEl.videoWidth || containerWidth
|
||||||
const videoHeight = videoEl.videoHeight || containerHeight
|
const videoHeight = videoEl.videoHeight || containerHeight
|
||||||
|
|
||||||
const scale = Math.min(containerWidth / videoWidth, containerHeight / videoHeight)
|
const scale = Math.min(containerWidth / videoWidth, containerHeight / videoHeight)
|
||||||
const drawWidth = videoWidth * scale
|
const drawWidth = videoWidth * scale
|
||||||
const drawHeight = videoHeight * scale
|
const drawHeight = videoHeight * scale
|
||||||
|
|
@ -1970,9 +1957,9 @@ export default {
|
||||||
|
|
||||||
// 将视频帧居中绘制
|
// 将视频帧居中绘制
|
||||||
ctx.drawImage(videoEl, offsetX, offsetY, drawWidth, drawHeight)
|
ctx.drawImage(videoEl, offsetX, offsetY, drawWidth, drawHeight)
|
||||||
|
|
||||||
const frameBase64 = tempCanvas.toDataURL('image/png')
|
const frameBase64 = tempCanvas.toDataURL('image/png')
|
||||||
|
|
||||||
// 创建一个 img 标签遮盖在 video 上
|
// 创建一个 img 标签遮盖在 video 上
|
||||||
tempImg = document.createElement('img')
|
tempImg = document.createElement('img')
|
||||||
tempImg.src = frameBase64
|
tempImg.src = frameBase64
|
||||||
|
|
@ -1982,7 +1969,7 @@ export default {
|
||||||
tempImg.style.width = '100%'
|
tempImg.style.width = '100%'
|
||||||
tempImg.style.height = '100%'
|
tempImg.style.height = '100%'
|
||||||
tempImg.style.zIndex = '99'
|
tempImg.style.zIndex = '99'
|
||||||
|
|
||||||
const videoContainer = this.$refs[`video-content-main-${this.activeCanvasIndex}`][0]
|
const videoContainer = this.$refs[`video-content-main-${this.activeCanvasIndex}`][0]
|
||||||
videoContainer.style.position = 'relative'
|
videoContainer.style.position = 'relative'
|
||||||
videoContainer.appendChild(tempImg)
|
videoContainer.appendChild(tempImg)
|
||||||
|
|
@ -1998,11 +1985,11 @@ export default {
|
||||||
// 等待 DOM 更新
|
// 等待 DOM 更新
|
||||||
await this.$nextTick()
|
await this.$nextTick()
|
||||||
|
|
||||||
const canvas = await html2canvas(divForDownloadViewport, {
|
const canvas = await html2canvas(divForDownloadViewport, {
|
||||||
useCORS: true,
|
useCORS: true,
|
||||||
backgroundColor: '#000000' // 指定截图背景为黑色
|
backgroundColor: '#000000' // 指定截图背景为黑色
|
||||||
})
|
})
|
||||||
|
|
||||||
// 截图后恢复
|
// 截图后恢复
|
||||||
if (tempImg) {
|
if (tempImg) {
|
||||||
tempImg.remove()
|
tempImg.remove()
|
||||||
|
|
@ -2010,7 +1997,7 @@ export default {
|
||||||
|
|
||||||
const base64Str = canvas.toDataURL('image/png', 1)
|
const base64Str = canvas.toDataURL('image/png', 1)
|
||||||
const downloadName = `${Date.now()}.png`
|
const downloadName = `${Date.now()}.png`
|
||||||
|
|
||||||
const a = document.createElement('a')
|
const a = document.createElement('a')
|
||||||
a.href = base64Str
|
a.href = base64Str
|
||||||
a.download = downloadName
|
a.download = downloadName
|
||||||
|
|
@ -2600,11 +2587,13 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.personal_config {
|
.personal_config {
|
||||||
::v-deep .el-tabs__content {
|
::v-deep .el-tabs__content {
|
||||||
height: 450px;
|
height: 450px;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .hot-keys-label {
|
::v-deep .hot-keys-label {
|
||||||
color: #dfdfdf !important;
|
color: #dfdfdf !important;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue