Merge branch 'uat'
continuous-integration/drone/push Build is passing Details

# Conflicts:
#	src/views/login/index.vue
#	src/views/trials/trials-layout/components/trialsNavbar.vue
#	src/views/trials/trials-panel/reading/dicoms/components/DicomCanvas.vue
#	src/views/trials/trials-panel/reading/dicoms/customize/CustomizeDicomCanvas.vue
#	src/views/trials/trials-panel/reading/dicoms/customize/CustomizeDicomViewer.vue
uat_us
wangxiaoshuang 2024-07-03 13:29:35 +08:00
commit cf7c7cbbc1
17 changed files with 1505 additions and 857 deletions

View File

@ -2,7 +2,7 @@
ENV = 'usa'
NODE_ENV = 'usa'
# base public path
VUE_APP_BASE_PATH = 'https://ei-code-prod.s3.amazonaws.com/2024-04-30/'
VUE_APP_BASE_PATH = 'https://ei-code-prod.s3.amazonaws.com/2024-07-03/'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = false

View File

@ -1,6 +1,6 @@
{
"name": "EICS",
"version": "1.0.0",
"version": "1.3.2",
"scripts": {
"dev": "vue-cli-service serve --open --mode development",
"build": "vue-cli-service build",

View File

@ -246,8 +246,11 @@ textarea {
color: $light_gray;
text-align: center;
font-weight: bold;
font-family: 'Times New Roman';
text-shadow:1px 0.5px 1.5px #666;
font-family: "Times New Roman";
text-shadow: 1px 0.5px 1.5px #666;
}
.title-logo {
height: 40px;
}
.title-logo{
height: 40px;

View File

@ -493,13 +493,15 @@ const actions = {
})
},
removeCustomizeMeasuredData({ state }, obj) {
return new Promise(async resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
var measureData = state.visitTaskList[index].MeasureData
console.log('removeCustomizeMeasuredData',obj, state.visitTaskList[index].MeasureData)
// var uuid = obj.measureData.data.uuid
// var idx = measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
console.log(obj, measureData)
// console.log(obj, measureData)
if (obj.questionInfo.Id) {
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
console.log('idx', idx)
if (idx > -1) {
@ -510,10 +512,13 @@ const actions = {
measureData.splice(idx, 1)
console.log('移除标记成功', idx)
}
if (obj.questionInfo.Id && state.currentReadingTaskState < 2) {
await deleteCustomTag(obj.questionInfo.Id)
}
state.visitTaskList[index].MeasureData = measureData
}
} else if (obj.orderMarkName) {
const i = measureData.findIndex(item => item.QuestionId === obj.questionId && item.OrderMarkName === obj.orderMarkName)
const i = measureData.findIndex(item => item.MeasureData.data.remark === obj.orderMarkName)
if (i > -1) {
if (measureData[i].FristAddTaskId) {
measureData[i].MeasureData = ''
@ -523,7 +528,9 @@ const actions = {
console.log('移除标记成功', i)
}
}
if (obj.questionInfo.Id && state.currentReadingTaskState < 2) {
await deleteCustomTag(obj.questionInfo.Id)
}
state.visitTaskList[index].MeasureData = measureData
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
@ -605,6 +612,7 @@ const actions = {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
var measureData = state.visitTaskList[index].MeasureData
console.log('addOrUpdateNonTargetMeasuredData')
// item.MeasureData.data.remark === obj.orderMarkName
var idx = measureData.findIndex(item => item.QuestionId === obj.data.QuestionId && item.OrderMarkName === obj.data.OrderMarkName)
if (idx > -1) {
for (const k in state.visitTaskList[index].MeasureData[idx]) {
@ -647,29 +655,39 @@ const actions = {
var measureData = state.visitTaskList[index].MeasureData
console.log(measureData, obj)
// var idx = measureData.findIndex(item => item.MeasureData.uuid === obj.data.MeasureData.data.uuid)
if (!obj.questionInfo) {
state.visitTaskList[index].MeasureData.push({
MeasureData: obj,
SeriesId: obj.seriesId,
StudyId: obj.studyId,
InstanceId: obj.instanceId,
Id: obj.Id
})
console.log('新增标记成功')
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
// if (!obj.questionInfo) {
// state.visitTaskList[index].MeasureData.push({
// MeasureData: obj,
// SeriesId: obj.seriesId,
// StudyId: obj.studyId,
// InstanceId: obj.instanceId,
// Id: obj.Id
// })
// console.log('新增标记成功')
// resolve()
// }
var idx = measureData.findIndex(item => item.MeasureData.data.remark === obj.measureData.data.remark)
if (idx > -1) {
for (const k in state.visitTaskList[index].MeasureData[idx]) {
if (k !== 'Id' && obj.MeasureData.data[k]) {
state.visitTaskList[index].MeasureData[idx][k] = obj.MeasureData.data[k]
}
}
// state.visitTaskList[index].MeasureData[idx].InstanceId = obj.instanceId
state.visitTaskList[index].MeasureData[idx].MeasureData = obj.measureData
// state.visitTaskList[index].MeasureData[idx].SeriesId = obj.seriesId
// state.visitTaskList[index].MeasureData[idx].StudyId = obj.studyId
// for (const k in state.visitTaskList[index].MeasureData[idx]) {
// if (k !== 'Id' && obj.MeasureData.data[k]) {
// state.visitTaskList[index].MeasureData[idx][k] = obj.MeasureData.data[k]
// }
// }
// state.visitTaskList[index].MeasureData[idx].MeasureData = obj.data.MeasureData
console.log('更新标记成功', idx)
} else {
state.visitTaskList[index].MeasureData.push(obj.MeasureData.data)
// state.visitTaskList[index].MeasureData.push(obj.MeasureData.data)
state.visitTaskList[index].MeasureData.push({
MeasureData: obj.measureData ,
SeriesId: obj.measureData.seriesId,
StudyId: obj.measureData.studyId,
InstanceId: obj.measureData.instanceId,
Id: obj.id
})
console.log('新增标记成功')
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
@ -878,6 +896,12 @@ const actions = {
resolve()
})
},
setImageloadedInfo({ state }, obj) {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
let prefetchInstanceCount = state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount
state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].prefetchInstanceCount = prefetchInstanceCount + 100
state.visitTaskList[index].StudyList[obj.studyIndex].SeriesList[obj.seriesIndex].imageloadedArr.push(obj.imageId)
},
setStatus({ state }, obj) {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
state.visitTaskList[index].IsInit = true

View File

@ -11,6 +11,7 @@
v-else-if="NODE_ENV === 'usa'"
src="@/assets/zzlogo-usa.png"
alt=""
class="usa-logo"
/>
<img v-else src="@/assets/zzlogo4.png" alt="" />
</div>
@ -21,12 +22,10 @@
<div class="login-r">
<div class="title-container">
<!-- IRC Management System -->
<img
src="@/assets/title-logo.png"
alt=""
class="title-logo"
v-if="NODE_ENV === 'usa'"
/>
<div v-if="NODE_ENV === 'usa'">
<img src="@/assets/title-logo.png" alt="" class="title-logo" />
<div class="title-logo-message">{{ $t("login:title:system") }}</div>
</div>
<div class="title" v-else>{{ $t("login:title:system") }}</div>
</div>
<el-form
@ -473,6 +472,9 @@ $light_gray: #606266;
img {
height: 40px;
}
.usa-logo {
height: 60px;
}
}
.login-image {
position: absolute;
@ -493,7 +495,7 @@ $light_gray: #606266;
.login-form {
position: absolute;
top: 50%;
top: 55%;
// transform: translateY(-50%);
left: 50%;
transform: translate(-50%, -50%);
@ -512,6 +514,12 @@ $light_gray: #606266;
text-align: center;
font-weight: bold;
}
.title-logo-message {
font-size: 26px;
color: $light_gray;
text-align: center;
margin-top: 20px;
}
}
.tips {

View File

@ -1,18 +1,17 @@
<template>
<div class="trials-navbar" style="position: relative">
<div class="leftMenu">
<img v-if="language === 'zh'" src="@/assets/zzlogo2.png" alt="">
<img v-else-if="NODE_ENV === 'usa'" src="@/assets/zzlogo-usa.png" alt="" />
<img v-else src="@/assets/zzlogo4.png" alt="">
<img v-if="language === 'zh'" src="@/assets/zzlogo2.png" alt="" />
<img
v-else-if="NODE_ENV === 'usa'"
src="@/assets/title-logo.png"
alt=""
class="title-logo"
v-if="NODE_ENV === 'usa'"
/>
<span style="white-space:nowrap;" v-else>
<img v-else src="@/assets/zzlogo4.png" alt="" />
<span style="white-space: nowrap">
<!-- 中心影像系统EICS -->
{{ $t('trials:trials:title:eics') }}
{{ $t("trials:trials:title:eics") }}
</span>
</div>
<div class="center-menu">
@ -26,22 +25,45 @@
size="mini"
@select="handleSelect"
>
<el-menu-item v-if="!hasPermi(['role:air', 'role:rpm', 'role:radmin', 'role:rcrc', 'role:rir'])" index="1">
<el-menu-item
v-if="
!hasPermi([
'role:air',
'role:rpm',
'role:radmin',
'role:rcrc',
'role:rir',
])
"
index="1"
>
<i class="el-icon-odometer" />
<!-- 工作台 -->
<span slot="title">{{ $t('trials:menuTitle:workbench') }}</span>
<span slot="title">{{ $t("trials:menuTitle:workbench") }}</span>
</el-menu-item>
<el-menu-item v-if="!hasPermi(['role:zys','role:zyss','role:zybs'])" index="2" :disabled="TotalNeedSignSystemDocCount !== 0">
<i class="el-icon-box" />
<!-- 我的项目 -->
<span slot="title">
{{ $t('trials:tab:trials') }}
{{ $t("trials:tab:trials") }}
</span>
</el-menu-item>
<el-menu-item v-if="!hasPermi(['role:air', 'role:rpm', 'role:radmin', 'role:rcrc', 'role:rir', 'role:zys'])" index="3">
<el-menu-item
v-if="
!hasPermi([
'role:air',
'role:rpm',
'role:radmin',
'role:rcrc',
'role:rir',
'role:zys',
])
"
index="3"
>
<i class="el-icon-chat-dot-square" />
<!-- 通知消息 -->
<span slot="title">{{ $t('trials:tab:notice') }}</span>
<span slot="title">{{ $t("trials:tab:notice") }}</span>
</el-menu-item>
<el-submenu index="4" class="my_info">
@ -52,7 +74,9 @@
<span v="userTypeShortName">({{ userTypeShortName }})</span> -->
</span>
<!-- 账户信息 -->
<el-menu-item v-if="!hasPermi(['role:air'])" index="4-2">{{ $t('trials:trials-myinfo:title:accountInfo') }}</el-menu-item>
<el-menu-item v-if="!hasPermi(['role:air'])" index="4-2">{{
$t("trials:trials-myinfo:title:accountInfo")
}}</el-menu-item>
<!-- 管理后台 -->
<el-menu-item
v-if="hasPermi(['role:dev', 'role:oa', 'role:admin'])"
@ -60,112 +84,123 @@
>{{ $t("trials:trials-myinfo:title:system") }}</el-menu-item
>
<!-- 退出 -->
<el-menu-item index="4-3">{{ $t('trials:trials-myinfo:button:loginout') }}</el-menu-item>
<el-menu-item index="4-3">{{
$t("trials:trials-myinfo:button:loginout")
}}</el-menu-item>
</el-submenu>
</el-menu>
<TopLang v-if="VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1'"/>
<TopLang v-if="VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1'" />
</div>
</div>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
import TopLang from './topLang'
import NoticeMarquee from './noticeMarquee'
import { mapGetters, mapMutations } from "vuex";
import TopLang from "./topLang";
import NoticeMarquee from "./noticeMarquee";
export default {
components: { TopLang, NoticeMarquee },
data() {
return {
activeIndex: '2',
activeIndex: "2",
isReviewer: false,
userTypeShortName: zzSessionStorage.getItem('userTypeShortName'),
notice: '',
userTypeShortName: zzSessionStorage.getItem("userTypeShortName"),
notice: "",
VUE_APP_OSS_CONFIG_REGION: process.env.VUE_APP_OSS_CONFIG_REGION,
NODE_ENV: process.env.NODE_ENV,
}
};
},
computed: {
...mapGetters(['sidebar', 'name', 'userName', 'device', 'TotalNeedSignSystemDocCount', 'language'])
...mapGetters([
"sidebar",
"name",
"userName",
"device",
"TotalNeedSignSystemDocCount",
"language",
]),
},
watch: {
$route(v) {
this.changeRoute(v)
}
this.changeRoute(v);
},
},
created() {
console.log(!this.hasPermi(['role:air']))
this.isReviewer = JSON.parse(zzSessionStorage.getItem('IsReviewer'))
this.changeRoute(this.$route)
console.log(!this.hasPermi(["role:air"]));
this.isReviewer = JSON.parse(zzSessionStorage.getItem("IsReviewer"));
this.changeRoute(this.$route);
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
...mapMutations({ setLanguage: "lang/setLanguage" }),
changeRoute(v) {
if (v.path === '/trials/trials-workbench') {
this.activeIndex = '1'
if (v.path === "/trials/trials-workbench") {
this.activeIndex = "1";
}
if (v.path === '/trials/trials-list' || ~v.path.indexOf('/trials/trials-panel')) {
this.activeIndex = '2'
if (
v.path === "/trials/trials-list" ||
~v.path.indexOf("/trials/trials-panel")
) {
this.activeIndex = "2";
}
if (v.path === '/trials/trials-notice') {
this.activeIndex = '3'
if (v.path === "/trials/trials-notice") {
this.activeIndex = "3";
}
if (v.path === '/trials/trials-myinfo') {
this.activeIndex = '4-2'
if (v.path === "/trials/trials-myinfo") {
this.activeIndex = "4-2";
}
},
handleSelect(key, keyPath) {
switch (key) {
case '4-2':
this.go('/trials/trials-myinfo')
break
case '4-3':
this.logout()
break
case "4-2":
this.go("/trials/trials-myinfo");
break;
case "4-3":
this.logout();
break;
case "4-4":
this.go("/system");
break;
case '1':
this.go('/trials/trials-workbench')
break
case '2':
if (~this.$route.path.indexOf('/trials/trials-panel')) {
return
case "1":
this.go("/trials/trials-workbench");
break;
case "2":
if (~this.$route.path.indexOf("/trials/trials-panel")) {
return;
}
var lastWorkbench = zzSessionStorage.getItem('lastWorkbench')
var lastWorkbench = zzSessionStorage.getItem("lastWorkbench");
if (lastWorkbench) {
this.go(lastWorkbench)
this.go(lastWorkbench);
} else {
this.go('/trials/trials-list')
this.go("/trials/trials-list");
}
break
case '3':
this.go('/trials/trials-notice')
break
break;
case "3":
this.go("/trials/trials-notice");
break;
}
},
toggleSideBar() {
this.$store.dispatch('app/toggleSideBar')
this.$store.dispatch("app/toggleSideBar");
},
async logout() {
await this.$store.dispatch('user/logout')
this.$router.push(`/login`)
this.$i18n.locale = 'zh'
this.setLanguage('zh')
this.$updateDictionary()
await this.$store.dispatch("user/logout");
this.$router.push(`/login`);
this.$i18n.locale = "zh";
this.setLanguage("zh");
this.$updateDictionary();
},
go(value) {
this.$router.push({ path: value })
this.$router.push({ path: value });
},
account() {
this.$router.push({ name: 'Account' })
}
}
}
this.$router.push({ name: "Account" });
},
},
};
</script>
<style lang="scss" scoped>
.trials-navbar{
.trials-navbar {
display: flex;
flex-direction: row;
justify-content: space-between;
@ -173,24 +208,29 @@ export default {
overflow: hidden;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
.el-breadcrumb__item{
.el-breadcrumb__item {
font-size: 16px;
}
.leftMenu{
.leftMenu {
display: flex;
align-items: center;
align-items: flex-end;
padding-left: 20px;
img{
padding-bottom: 20px;
img {
height: 28px;
margin-right: 10px;
}
span{
.title-logo {
height: 32px;
}
span {
font-size: 20px;
position: relative;
top: -1px;
bottom: -3px;
}
}
.right-menu, .center-menu {
.right-menu,
.center-menu {
display: flex;
flex-direction: row;
justify-content: space-between;
@ -240,7 +280,7 @@ export default {
}
</style>
<style>
.el-menu--horizontal>.my_info.el-submenu .el-submenu__icon-arrow {
.el-menu--horizontal > .my_info.el-submenu .el-submenu__icon-arrow {
margin-top: 0;
}
}
</style>

View File

@ -13,7 +13,7 @@
<!-- 临床数据 -->
<div v-if="stack.isExistsClinicalData" class="info-cd" @click.stop="handleViewCD($event)">
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:clinicalData')" placement="bottom">
<svg-icon icon-class="documentation" class="svg-icon" />
<svg-icon icon-class="documentation" class="svg-icon"/>
</el-tooltip>
</div>

View File

@ -51,7 +51,7 @@
<div class="flex-div">
<div style="width: 40px;display: flex;flex-direction: row;justify-content: space-between;">
<div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }}</div>
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount && series.modality!== 'SR'">
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount * 100 && series.modality!== 'SR'">
<!-- 下载 -->
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
@ -219,7 +219,8 @@ export default {
srInfo: {},
digitPlaces: 2,
visitTaskIdx: -1,
currentLoadIns: []
currentLoadIns: [],
keySeriesLoad: []
}
},
@ -299,11 +300,14 @@ export default {
//
this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer()
res.map((item) => {
res.map(async(item) => {
// this.loadInitialImage(item)
const imageId = item.imageIds[item.imageIdIndex]
const p = parseInt(new Date().getTime())
requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
await requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
if (!item.isCurrentTask) {
store.dispatch('reading/setImageloadedInfo', item)
}
})
var i = res.findIndex(s => s.isCurrentTask)
if (i > -1) {
@ -913,6 +917,23 @@ export default {
const studyIndex = parseInt(params.idx.split('|')[0])
const seriesIndex = parseInt(params.idx.split('|')[1])
//
const seriesId = this.studyList[studyIndex].SeriesList[seriesIndex].seriesId
const i = this.keySeriesLoad.findIndex(i => i.seriesId === seriesId)
if (this.studyList[studyIndex].IsCriticalSequence && percentComplete >= 100) {
//
if (i === -1) {
this.keySeriesLoad.push({ seriesId: seriesId, loadCount: 1, imageIds: [imageId] })
} else {
++this.keySeriesLoad[i].loadCount
this.keySeriesLoad[i].imageIds.push(imageId)
}
}
if (!this.studyList[studyIndex].IsCriticalSequence && i > -1) {
this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount + 100 * this.keySeriesLoad[i].loadCount
this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr = [this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr, this.keySeriesLoad[i].imageIds]
this.keySeriesLoad.splice(i, 1)
}
var prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount
var instanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount
if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {

View File

@ -146,6 +146,7 @@ import LengthTool from '@/views/trials/trials-panel/reading/dicoms/tools/Length/
import BidirectionalTool from '@/views/trials/trials-panel/reading/dicoms/tools/Bidirectional/BidirectionalTool'
import ArrowAnnotateTool from '@/views/trials/trials-panel/reading/dicoms/tools/ArrowAnnotate/ArrowAnnotateTool'
import RectangleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/RectangleRoi/RectangleRoiTool'
import CircleRoiTool from '@/views/trials/trials-panel/reading/dicoms/tools/CircleRoi/CircleRoiTool'
// import OrientationMarkersTool from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/OrientationMarkersTool'
import ScaleOverlayTool from '@/views/trials/trials-panel/reading/dicoms/tools/ScaleOverlay/ScaleOverlayTool'
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
@ -258,7 +259,7 @@ export default {
series: '',
ToolStateManager: null,
renderedMeasured: [],
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate', 'RectangleRoi'],
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate', 'RectangleRoi', 'CircleRoi'],
measureData: [],
selectedLesion: null,
activeTool: 0, // 0:enable 1:passive 2:active
@ -298,8 +299,8 @@ export default {
],
scrollSyncInfo: { offset: 0 },
hideMeasureArr: []
hideMeasureArr: [],
enabledElement: null
}
},
computed: {
@ -399,7 +400,8 @@ export default {
cornerstone.updateImage(this.canvas, true)
})
DicomEvent.$on('updateImage', () => {
cornerstone.updateImage(this.canvas)
if (!this.canvas) return
this.updateImage()
})
// this.canvas.addEventListener('keydown', event => {
// event.preventDefault()
@ -542,7 +544,7 @@ export default {
this.mousePosition.y = currentPoints.image.y + 1
this.mousePosition.mo = stats.mo
this.mousePosition.suv = stats.suv
if (this.isFirstChangeTask && this.pointNearTool(e)) {
if (this.pointNearTool(e)) {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
@ -551,18 +553,18 @@ export default {
mouseUp(e) {
console.log('mouseUp')
if (this.readingTaskState >= 2) return
// if (this.readingTaskState >= 2) return
this.image = e.detail.image
this.getToolStateInfo(e)
},
mouseDown(e) {
this.image = e.detail.image
var pointNearTool = this.pointNearTool(e)
if (this.isFirstChangeTask && pointNearTool) {
if (pointNearTool) {
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
} else if (this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional' && this.readingTaskState < 2) {
} else if (this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional') {
if (!e.detail.image.columnPixelSpacing || !e.detail.image.rowPixelSpacing) {
// ''
this.$confirm(this.$t('trials:reading:warnning:msg56'), '', {
@ -601,10 +603,11 @@ export default {
getDisabledMarks(measureDatas) {
var arr = []
measureDatas.map(i => {
if ((i.LesionType === 0 || i.LesionType === 1 || i.LesionType === 7) && i.IsFirstChangeTask) {
arr.push(i.OrderMarkName)
if (i.Id && this.readingTaskState >= 2) {
arr.push(i.MeasureData.data.remark)
}
})
console.log(arr)
return arr
},
getRGBPixels(element, x, y, width, height) {
@ -776,7 +779,7 @@ export default {
var uuid = toolState.data[i].uuid
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) {
var markName = this.measureData[idx].OrderMarkName
var markName = this.measureData[idx].MeasureData.data.remark
if (this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) {
measureData.ww = Math.round(viewport.voi.windowWidth)
measureData.wc = Math.round(viewport.voi.windowCenter)
@ -882,7 +885,9 @@ export default {
} else if (this.activeTool === 1 && this.readingTaskState < 2) {
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
} else {
cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
// cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
}
// console.log('renderMeasuredData', this.stack.frame)
@ -984,17 +989,17 @@ export default {
if (i > -1) {
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
if (idx > -1) {
console.log('mouseClick')
DicomEvent.$emit('setCollapseActive', this.measureData[idx])
if (this.readingTaskState < 2) {
const measureData = {}
var markName = this.measureData[idx].OrderMarkName
if (this.activeToolName === 'Eraser') {
var questionInfo = this.measureData[idx]
this.$emit('moveMeasureData', { measureData, questionInfo })
// var markName = this.measureData[idx].OrderMarkName
var markName = this.measureData[idx].MeasureData.data.remark
if (this.activeToolName === 'Eraser' && this.disabledMarks.indexOf(markName) === -1) {
const questionInfo = this.measureData[idx]
measureData.orderMarkName = markName
this.$emit('moveMeasureData', { measureData, questionInfo, orderMarkName: markName})
}
if ((this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) && this.activeToolName !== 'Eraser') {
var questionInfo = this.measureData[idx]
const questionInfo = this.measureData[idx]
const canvas = this.canvas.querySelector('canvas')
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
measureData.studyId = this.stack.studyId
@ -1010,7 +1015,7 @@ export default {
measureData.data.active = false
this.$emit('modifyMeasureData', { measureData, questionInfo })
}
}
break
}
}
@ -1049,11 +1054,7 @@ export default {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === dicomSeries.visitTaskId)
this.stack.visitTaskNum = this.visitTaskList[idx].VisitTaskNum
this.isFirstChangeTask = this.visitTaskList[idx].IsFirstChangeTask
if (this.isFirstChangeTask) {
this.disabledMarks = this.getDisabledMarks(this.visitTaskList[idx].MeasureData)
} else {
this.disabledMarks = []
}
this.maxVistNum = this.visitTaskList[this.visitTaskList.length - 1].VisitTaskNum
this.minVistNum = this.visitTaskList[0].VisitTaskNum
@ -1114,7 +1115,6 @@ export default {
if (!this.toolState.initialized) {
this.toolState.initialized = true
const toolButtons = document.querySelectorAll('[data-tool]')
// const scope = this
Array.from(toolButtons).forEach((toolBtn) => {
// Add the tool
@ -1134,6 +1134,8 @@ export default {
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
} else if (toolName === 'RectangleRoi') {
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
} else if (toolName === 'CircleRoi') {
cornerstoneTools.addToolForElement(element, CircleRoiTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true, showMinMax: true }})
} else {
cornerstoneTools.addToolForElement(element, apiTool)
}
@ -1221,8 +1223,8 @@ export default {
if (this.dicomInfo.thick) {
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
}
let newImageIdIndex = this.stack.imageIds.findIndex(i=>i===imageId)
if(newImageIdIndex === -1) return
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === imageId)
if (newImageIdIndex === -1) return
this.stack.currentImageIdIndex = newImageIdIndex
this.stack.imageIdIndex = newImageIdIndex
this.series.imageIdIndex = newImageIdIndex
@ -1298,7 +1300,7 @@ export default {
this.setMarkers()
},
onMeasurementcompleted(e) {
if (this.readingTaskState >= 2) return
// if (this.readingTaskState >= 2) return
var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport
@ -1310,8 +1312,8 @@ export default {
const imageInfo = this.getInstanceInfo(imageId)
var instanceId = imageInfo.instanceId
var frame = imageInfo.frame
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi') {
this.stack.frame = !isNaN(parseInt(frame)) ? parseInt(frame) : 0
if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi' || e.detail.toolName === 'CircleRoi') {
const measureData = {}
measureData.studyId = this.stack.studyId
measureData.seriesId = this.stack.seriesId
@ -1326,6 +1328,7 @@ export default {
const canvas = this.canvas.querySelector('canvas')
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
measureData.temporary = this.readingTaskState >= 2
this.$emit('setMeasureData', measureData)
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
} else if (e.detail.toolName === 'Bidirectional') {
@ -1342,6 +1345,7 @@ export default {
measureData.wc = Math.round(viewport.voi.windowCenter)
const canvas = this.canvas.querySelector('canvas')
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
measureData.temporary = this.readingTaskState >= 2
this.$emit('setMeasureData', measureData)
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
} else if (!e.detail.toolName) {
@ -1422,7 +1426,7 @@ export default {
onMeasurementmodified(e) {
//
console.log('modified')
if (this.readingTaskState >= 2) return
// if (this.readingTaskState >= 2) return
const { measurementData, toolType } = e.detail
var element = cornerstone.getEnabledElement(this.canvas)
var viewport = element.viewport
@ -1436,7 +1440,8 @@ export default {
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === uuid)
if (idx > -1) {
const measureData = {}
var markName = this.measureData[idx].OrderMarkName
// var markName = this.measureData[idx].OrderMarkName
var markName = this.measureData[idx].MeasureData.data.remark
if (this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) {
var questionInfo = this.measureData[idx]
const canvas = this.canvas.querySelector('canvas')
@ -1466,15 +1471,21 @@ export default {
}
},
updateImage(instanceId) {
if (!this.canvas) return
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
this.measureData = this.visitTaskList[i].MeasureData
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
var element = cornerstone.getEnabledElement(this.canvas)
if (!element) return
var { imageId } = element.image
if (imageId) {
ToolStateManager.clearImageIdToolState(imageId)
cornerstone.updateImage(element, true)
let elements = cornerstone.getEnabledElementsByImageId(imageId)
elements.map(el=>{
cornerstone.updateImage(el.element)
})
}
// cornerstone.updateImage(element)
},
toggleSeries(evt, type) {
evt.stopImmediatePropagation()
@ -1756,20 +1767,19 @@ export default {
this.activeToolName = toolName
this.$nextTick(() => {
// console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional'))
if (!cornerstoneTools.isToolActiveForElement(this.canvas, toolName)) {
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
mouseButtonMask: 1
})
}
if (toolName === 'Zoom') {
cornerstoneTools.setToolActiveForElement(this.canvas, 'Zoom', {
mouseButtonMask: [1, 2]
})
}
if (toolName === 'Pan') {
} else if (toolName === 'Pan') {
cornerstoneTools.setToolActiveForElement(this.canvas, 'Pan', {
mouseButtonMask: [1, 4]
})
} else {
cornerstoneTools.setToolActiveForElement(this.canvas, toolName, {
mouseButtonMask: 1
})
}
})
},

View File

@ -217,9 +217,12 @@ export default {
this.measureData = measureData
},
modifyMeasuredData(measureData) {
console.log(measureData)
measureData.visitTaskId = this.visitTaskId
measureData.measureData.pictureBaseStr = ''
if (this.readingTaskState >=2) {
this.measuredDataVisible = false
store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: measureData.measureData })
}else{
let params = JSON.parse(JSON.stringify(measureData))
params.measureData = JSON.stringify(measureData.measureData)
params.Id = params.questionInfo.Id
@ -229,7 +232,10 @@ export default {
submitCustomTag(params).then(() => {
this.measuredDataVisible = false
DicomEvent.$emit('updateImage')
// this.$message.success(this.$t('common:message:savedSuccessfully'))
})
}
},
async moveMeasureData(measureData) {
console.log('measureData', measureData)
@ -238,24 +244,46 @@ export default {
},
handleMeasuredDataCancel() {
this.measuredDataVisible = false
DicomEvent.$emit('updateImage')
},
handleMeasuredDataSave() {
this.$refs.measuredDataForm.validate(valid => {
if (!valid) return
//
let isValid = this.validateRemarkName(this.form.measuredDataName)
if (!isValid) {
// ''
this.$message.error(this.$t('trials:customReading:error:validMarkName'))
return
}
this.measureData.data.remark = this.form.measuredDataName
this.measureData.pictureBaseStr = ''
if (this.readingTaskState >=2) {
this.measuredDataVisible = false
this.form.measuredDataName = ''
store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.measureData })
DicomEvent.$emit('updateImage')
this.$message.success(this.$t('common:message:savedSuccessfully'))
} else {
let params = JSON.parse(JSON.stringify(this.measureData))
params.measureData = JSON.stringify(this.measureData)
submitCustomTag(params).then(async (res) => {
this.measuredDataVisible = false
this.form.measuredDataName = ''
this.measureData.Id = res.Result
await store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, ...this.measureData })
await store.dispatch('reading/addCustomizeMeasuredData', { visitTaskId: this.visitTaskId, measureData: this.measureData, id: res.Result })
await store.dispatch('reading/getCustomizeMeasuredData', this.visitTaskId)
DicomEvent.$emit('updateImage')
this.$message.success(this.$t('common:message:savedSuccessfully'))
})
}
})
},
validateRemarkName(remark) {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
var measureData = this.visitTaskList[idx].MeasureData
let i = measureData.findIndex(i=>i.MeasureData.data.remark === remark)
return i === -1
},
//
closeSignDialog(isSign, signInfo) {
if (isSign) {

View File

@ -51,7 +51,7 @@
<div class="flex-div">
<div style="width: 40px;display: flex;flex-direction: row;justify-content: space-between;">
<div v-if="!study.IsCriticalSequence">#{{ series.seriesNumber }}</div>
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount && series.modality!== 'SR'">
<div v-if="series.isDicom && series.prefetchInstanceCount<series.instanceCount * 100 && series.modality!== 'SR'">
<!-- 下载 -->
<el-tooltip v-if="!series.isLoading" class="item" effect="dark" :content="$t('trials:reading:button:download')" placement="bottom">
<i class="el-icon-video-play" style="font-size: 18px;margin-right: 5px;color: #ffeb3b;cursor: pointer;" @click.stop="loadSeries(series,index,i)" />
@ -218,7 +218,8 @@ export default {
srInfo: {},
digitPlaces: 2,
visitTaskIdx: -1,
currentLoadIns: []
currentLoadIns: [],
keySeriesLoad: []
}
},
@ -281,10 +282,14 @@ export default {
//
this.getInitSeries().then((res) => {
requestPoolManager.startTaskTimer()
res.map((item) => {
res.map(async(item) => {
let imageId = item.imageIds[item.imageIdIndex]
const p = parseInt(new Date().getTime())
requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
// requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
await requestPoolManager.loadAndCacheImagePlus(imageId, item.seriesId, p * 100)
if (!item.isCurrentTask) {
store.dispatch('reading/setImageloadedInfo', item)
}
})
var i = res.findIndex(s => s.isCurrentTask)
if (i > -1) {
@ -888,6 +893,23 @@ export default {
if (this.visitTaskId === params.visitTaskId) {
const studyIndex = params.idx.split('|')[0]
const seriesIndex = params.idx.split('|')[1]
const seriesId = this.studyList[studyIndex].SeriesList[seriesIndex].seriesId
const i = this.keySeriesLoad.findIndex(i => i.seriesId === seriesId)
if (this.studyList[studyIndex].IsCriticalSequence && percentComplete >= 100) {
//
if (i === -1) {
this.keySeriesLoad.push({ seriesId: seriesId, loadCount: 1, imageIds: [imageId] })
} else {
++this.keySeriesLoad[i].loadCount
this.keySeriesLoad[i].imageIds.push(imageId)
}
}
if (!this.studyList[studyIndex].IsCriticalSequence && i > -1) {
this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount + 100 * this.keySeriesLoad[i].loadCount
this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr = [this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr, this.keySeriesLoad[i].imageIds]
this.keySeriesLoad.splice(i, 1)
}
var prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount
var instanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount
if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {

View File

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

View File

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

View File

@ -224,11 +224,11 @@ export default {
IsEnable: true,
IsAutoSend: true,
CriterionTypeEnum: null,
FromEmail: 'test@extimaging.com',
FromName: 'Test_IRC',
AuthorizationCode: 'SHzyyl2021',
SMTPServerAddress: 'smtp.qiye.aliyun.com',
SMTPServerPort: 465,
FromEmail: '',
FromName: '',
AuthorizationCode: '',
SMTPServerAddress: '',
SMTPServerPort: null,
},
rules: {
Code: [{ required: true, message: 'Please select', trigger: ['blur'] }],

View File

@ -493,7 +493,7 @@
</el-tab-pane>
<!-- 临床数据采集 -->
<el-tab-pane
v-if="rowData.IsBaseLine && (otherInfo.IsHaveSubjectClinicalData||otherInfo.IsHaveVisitClinicalData)"
v-if="rowData.IsBaseLine && (otherInfo.IsHaveSubjectClinicalData || otherInfo.IsHaveVisitClinicalData)"
:label="$t('trials:uploadClinicalData:tab:uploadClinicalData')"
name="clinical-data"
>
@ -574,10 +574,11 @@
<UploadNonDicomFiles v-if="rowData.Id" :data="rowData" :subject-visit-id="rowData.Id" :body-parts="otherInfo.BodyPartTypes" :modalities="otherInfo.Modalitys" :allow-add-or-edit="false" @getList="getList"/>
</el-card>
<!-- 临床数据 -->
<h4 v-if="rowData.IsBaseLine && (otherInfo.IsHaveSubjectClinicalData||otherInfo.IsHaveVisitClinicalData)" class="box-title" style="margin-top:10px;">
<!-- 基线显示受试者级别和方式级别的临床数据 -->
<h4 v-if="rowData.IsBaseLine && otherInfo.ClinicalInformationTransmissionEnum > 0 && (otherInfo.IsHaveSubjectClinicalData || otherInfo.IsHaveVisitClinicalData)" class="box-title" style="margin-top:10px;">
{{ $t('trials:crcUpload:label:clinicalData') }}
</h4>
<el-card v-if="rowData.IsBaseLine && (otherInfo.IsHaveSubjectClinicalData||otherInfo.IsHaveVisitClinicalData)" class="box-card">
<el-card v-if="rowData.IsBaseLine && otherInfo.ClinicalInformationTransmissionEnum > 0 && (otherInfo.IsHaveSubjectClinicalData || otherInfo.IsHaveVisitClinicalData)" class="box-card">
<UploadClinicalData v-if="rowData.Id && rowData.IsBaseLine" :enum-type="otherInfo.ClinicalInformationTransmissionEnum" :allow-add-or-edit="false" :data="rowData" :subject-visit-id="rowData.Id" @getList="getList" />
</el-card>
<h4 v-if="!rowData.IsBaseLine && otherInfo.IsHaveVisitClinicalData" class="box-title" style="margin-top:10px;">