非DICOM影像质控时,可以设置影像为删除、不阅片
continuous-integration/drone/push Build is passing Details

uat
wangxiaoshuang 2025-03-05 16:14:29 +08:00
parent 5450188a6e
commit 86f5e2c782
3 changed files with 232 additions and 26 deletions

View File

@ -1080,7 +1080,13 @@ export function setSeriesStatus(trialId, subjectVisitId, studyId, seriesId, stat
method: 'put' method: 'put'
}) })
} }
export function setNodicomStudyState(params) {
return request({
url: `/QCOperation/setNodicomStudyState`,
method: 'put',
params
})
}
export function setInstanceStatus(trialId, subjectVisitId, seriesId, instanceId, state) { export function setInstanceStatus(trialId, subjectVisitId, seriesId, instanceId, state) {
return request({ return request({
url: `/QCOperation/setInstanceState/${trialId}/${subjectVisitId}/${seriesId}/${instanceId}/${state}`, url: `/QCOperation/setInstanceState/${trialId}/${subjectVisitId}/${seriesId}/${instanceId}/${state}`,

View File

@ -23,25 +23,48 @@
<slot name="empty">{{ $t('trials:audit:message:noData') }}</slot> <slot name="empty">{{ $t('trials:audit:message:noData') }}</slot>
</div> </div>
<div v-else id="imgList" style="height: 100%; overflow: hidden"> <div v-else id="imgList" style="height: 100%; overflow: hidden">
<div <template v-for="(item, j) in study.NoneDicomStudyFileList">
v-for="(item, j) in study.NoneDicomStudyFileList" <div
:id="`img${item.Id}`" :id="`img${item.Id}`"
:key="item.Id" :key="item.Id"
:class="{ :class="{
'is-boxActive': item.Id === currentFileId, 'is-boxActive': item.Id === currentFileId,
}" }"
class="img-box" class="img-box"
@click="selected(item, i, j, true)" @click="selected(item, i, j, true)"
> >
<div v-if="item.FileName.length < 15" class="img-text"> <div v-if="item.FileName.length < 15" class="img-text">
{{ `${j + 1}. ${item.FileName}` }}
</div>
<el-tooltip v-else :content="item.FileName" placement="bottom">
<div class="img-text">
{{ `${j + 1}. ${item.FileName}` }} {{ `${j + 1}. ${item.FileName}` }}
</div> </div>
</el-tooltip> <el-tooltip v-else :content="item.FileName" placement="bottom">
</div> <div class="img-text">
{{ `${j + 1}. ${item.FileName}` }}
</div>
</el-tooltip>
<div v-if="isQcCheck" class="switchBox">
<div class="item">
<span>{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="item.IsReading"
:disabled="item.IsDeleted || isAudit"
@change="changeReadingStatus($event, study, item)"
:active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)"
/>
</div>
<div class="item">
<span>{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="item.IsDeleted"
:disabled="isAudit"
@change="changeDeleteStatus($event, study, item)"
:active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)"
/>
</div>
</div>
</div>
</template>
</div> </div>
</div> </div>
</div> </div>
@ -70,7 +93,7 @@
</template> </template>
<script> <script>
import { getNoneDicomStudyList } from '@/api/trials' import { getNoneDicomStudyList, setNodicomStudyState } from '@/api/trials'
import store from '@/store' import store from '@/store'
import { changeURLStatic } from '@/utils/history.js' import { changeURLStatic } from '@/utils/history.js'
import Preview from './components/preview' import Preview from './components/preview'
@ -111,10 +134,14 @@ export default {
path: null, path: null,
type: null, type: null,
}, },
isQcCheck: false,
isAudit: false,
} }
}, },
async created() { async created() {
this.bp = await this.$getBodyPart(this.$route.query.trialId) this.bp = await this.$getBodyPart(this.$route.query.trialId)
this.isQcCheck = !!this.$route.query.isQcCheck
console.log(this.isQcCheck)
}, },
async mounted() { async mounted() {
if (this.$router.currentRoute.query.TokenKey) { if (this.$router.currentRoute.query.TokenKey) {
@ -127,6 +154,95 @@ export default {
// //
}, },
methods: { methods: {
changeReadingStatus(callback, row, file) {
let statusStr = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesReading')
file.IsReading = false
} else {
statusStr = this.$t('trials:audit:label:setSeriesNotReading')
file.IsReading = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace(
'xxx',
statusStr
)
message = message.replace('yyy', this.$fd('YesOrNo', !file.IsReading))
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning',
})
.then(() => {
const state = file.IsReading ? 1 : 2
this.loading = true
let params = {
SubjectVisitId: row.SubjectVisitId,
NoneDicomStudyId: row.Id,
State: state,
NoneDicomStudyFileId: file.Id,
}
return setNodicomStudyState(params)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('common:message:savedSuccessfully')
)
this.getNoneDicomList()
}
})
.catch(() => {
file.IsReading = !file.IsReading
this.loading = false
})
})
.catch(() => {})
},
changeDeleteStatus(callback, row, file) {
let statusStr = ''
if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
file.IsDeleted = false
} else {
statusStr = this.$t('trials:audit:label:setSeriesNotDelete')
file.IsDeleted = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace(
'xxx',
statusStr
)
message = message.replace('yyy', this.$fd('YesOrNo', !file.IsDeleted))
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning',
})
.then(() => {
const state = file.IsDeleted ? 5 : 4
this.loading = true
let params = {
SubjectVisitId: row.SubjectVisitId,
NoneDicomStudyId: row.Id,
State: state,
NoneDicomStudyFileId: file.Id,
}
return setNodicomStudyState(params)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('common:message:savedSuccessfully')
)
this.getNoneDicomList()
}
})
.catch(() => {
file.IsDeleted = !file.IsDeleted
this.loading = false
})
})
.catch(() => {})
},
getBodyPart(bodyPart) { getBodyPart(bodyPart) {
console.log(bodyPart) console.log(bodyPart)
if (!bodyPart) return '' if (!bodyPart) return ''
@ -163,6 +279,7 @@ export default {
.then((res) => { .then((res) => {
this.studyList = res.Result this.studyList = res.Result
this.OtherInfo = res.OtherInfo this.OtherInfo = res.OtherInfo
this.isAudit = res.OtherInfo.AuditState * 1 > 6
this.loading = false this.loading = false
const studyIndex = this.studyList.findIndex((item) => { const studyIndex = this.studyList.findIndex((item) => {
return item.NoneDicomStudyFileList.length > 0 return item.NoneDicomStudyFileList.length > 0
@ -328,4 +445,14 @@ export default {
width: 100%; width: 100%;
} }
} }
.switchBox {
margin-bottom: 5px;
color: #4e4e4e;
.item {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 5px;
}
}
</style> </style>

View File

@ -311,8 +311,8 @@
}} }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 更新时间 --> <!-- 更新时间 -->
<el-table-column <el-table-column
prop="UpdateTime" prop="UpdateTime"
:label="$t('trials:audit:table:seriesOfUpdateTime')" :label="$t('trials:audit:table:seriesOfUpdateTime')"
sortable sortable
@ -373,7 +373,6 @@
</el-tab-pane> </el-tab-pane>
<!-- 非DICOM影像 --> <!-- 非DICOM影像 -->
<el-tab-pane <el-tab-pane
v-if="data.NoneDicomStudyCount > 0"
:label="$t('trials:audit:tab:nonDicoms')" :label="$t('trials:audit:tab:nonDicoms')"
name="none-dicom" name="none-dicom"
> >
@ -448,6 +447,7 @@
<el-table <el-table
:data="noneDicomStudyList" :data="noneDicomStudyList"
@selection-change="handleSelectionChangeNonedicom" @selection-change="handleSelectionChangeNonedicom"
:row-class-name="tableRowClassName"
:default-sort="{ prop: 'CreateTime', order: 'ascending' }" :default-sort="{ prop: 'CreateTime', order: 'ascending' }"
> >
<el-table-column type="selection" width="55"> </el-table-column> <el-table-column type="selection" width="55"> </el-table-column>
@ -597,6 +597,38 @@
:label="$t('trials:audit:table:nonDicomsCreateTime')" :label="$t('trials:audit:table:nonDicomsCreateTime')"
sortable sortable
/> />
<!-- 是否阅片 -->
<el-table-column
prop="IsReading"
:label="$t('trials:audit:table:isReading')"
sortable
>
<template slot-scope="scope">
<el-switch
v-model="scope.row.IsReading"
:disabled="scope.row.IsDeleted || isAudit"
@change="changeReadingStatus($event, scope.row, true)"
:active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)"
/>
</template>
</el-table-column>
<!-- 是否删除 -->
<el-table-column
prop="IsDeleted"
:label="$t('trials:audit:table:isDelete')"
sortable
>
<template slot-scope="scope">
<el-switch
v-model="scope.row.IsDeleted"
:disabled="isAudit"
@change="changeDeleteStatus($event, scope.row, true)"
:active-text="$fd('YesOrNo', true)"
:inactive-text="$fd('YesOrNo', false)"
/>
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')"> <el-table-column :label="$t('common:action:action')">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 预览 --> <!-- 预览 -->
@ -1434,6 +1466,7 @@ import {
verifyCanQCPassedOrFailed, verifyCanQCPassedOrFailed,
verifyQCCanAddChallenge, verifyQCCanAddChallenge,
setSeriesStatus, setSeriesStatus,
setNodicomStudyState,
addOrUpdateNoneDicomStudy, addOrUpdateNoneDicomStudy,
addOrUpdateQCQuestionAnswerList, addOrUpdateQCQuestionAnswerList,
addOrUpdateQCChallenge, addOrUpdateQCChallenge,
@ -2119,7 +2152,7 @@ export default {
this.currentQCRow = { ...row } this.currentQCRow = { ...row }
this.chatVisible = true this.chatVisible = true
}, },
changeReadingStatus(callback, row) { changeReadingStatus(callback, row, isNoDicom = false) {
let statusStr = '' let statusStr = ''
if (callback) { if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesReading') statusStr = this.$t('trials:audit:label:setSeriesReading')
@ -2140,6 +2173,26 @@ export default {
.then(() => { .then(() => {
const state = row.IsReading ? 1 : 2 const state = row.IsReading ? 1 : 2
this.loading = true this.loading = true
if (isNoDicom) {
let params = {
SubjectVisitId: row.SubjectVisitId,
NoneDicomStudyId: row.Id,
State: state,
}
return setNodicomStudyState(params)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('common:message:savedSuccessfully')
)
this.getQCInfo()
}
})
.catch(() => {
this.loading = false
})
}
setSeriesStatus( setSeriesStatus(
this.trialId, this.trialId,
this.data.Id, this.data.Id,
@ -2162,7 +2215,7 @@ export default {
}) })
.catch(() => {}) .catch(() => {})
}, },
changeDeleteStatus(callback, row) { changeDeleteStatus(callback, row, isNoDicom = false) {
let statusStr = '' let statusStr = ''
if (callback) { if (callback) {
statusStr = this.$t('trials:audit:label:setSeriesDeleted') statusStr = this.$t('trials:audit:label:setSeriesDeleted')
@ -2183,6 +2236,26 @@ export default {
.then(() => { .then(() => {
const state = row.IsDeleted ? 5 : 4 const state = row.IsDeleted ? 5 : 4
this.loading = true this.loading = true
if (isNoDicom) {
let params = {
SubjectVisitId: row.SubjectVisitId,
NoneDicomStudyId: row.Id,
State: state,
}
return setNodicomStudyState(params)
.then((res) => {
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('common:message:savedSuccessfully')
)
this.getQCInfo()
}
})
.catch(() => {
this.loading = false
})
}
setSeriesStatus( setSeriesStatus(
this.trialId, this.trialId,
this.data.Id, this.data.Id,
@ -2632,7 +2705,7 @@ export default {
let trialId = this.$route.query.trialId let trialId = this.$route.query.trialId
var token = getToken() var token = getToken()
const routeData = this.$router.resolve({ const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&TokenKey=${token}`, path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&TokenKey=${token}&isQcCheck=1`,
}) })
this.open = window.open(routeData.href, '_blank') this.open = window.open(routeData.href, '_blank')
}, },
@ -2644,7 +2717,7 @@ export default {
let trialId = this.$route.query.trialId let trialId = this.$route.query.trialId
var token = getToken() var token = getToken()
const routeData = this.$router.resolve({ const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&studyId=${row.Id}&TokenKey=${token}`, path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&studyId=${row.Id}&TokenKey=${token}&isQcCheck=1`,
}) })
this.open = window.open(routeData.href, '_blank') this.open = window.open(routeData.href, '_blank')
}, },