在影像质控完成后,可以更正影像检查的基本信息,并且需要签名
continuous-integration/drone/push Build is passing Details

main
wangxiaoshuang 2025-07-31 16:09:44 +08:00
parent d911d55129
commit 5a8ec13c2f
4 changed files with 194 additions and 35 deletions

View File

@ -4204,4 +4204,20 @@ export function getExportSubjectVisitImageList(data) {
method: 'post',
data
})
}
// 影像质控-更正dicom
export function updateDicomStudyInfo(data) {
return request({
url: `/Inspection/QCOperation/UpdateDicomStudyInfo`,
method: 'post',
data
})
}
// 影像质控-更正非dicom
export function updateNoneDicomStudy(data) {
return request({
url: `/Inspection/NoneDicomStudy/UpdateNoneDicomStudy`,
method: 'post',
data
})
}

View File

@ -32,7 +32,7 @@ export default {
ResetImageQualityControlQuestion: 112, //
CreateReviewTask: 113, //
ReviewImageQualityControlQuestion: 219, //
CorrectImageExaminationInformation: 220, //
},
};
</script>

View File

@ -129,7 +129,7 @@
<!-- 上传时间 -->
<el-table-column prop="UploadedTime" :label="$t('trials:audit:table:seriesOfUploadedDate')"
min-width="120" sortable show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')">
<el-table-column :label="$t('common:action:action')" min-width="160">
<template slot-scope="scope">
<!-- 预览 -->
<el-button icon="el-icon-view" :title="$t('trials:audit:action:preview')" circle
@ -145,6 +145,9 @@
scope.row.Modalities
) && IsHaveStudyClinicalData
" circle :disabled="scope.row.IsDeleted" @click="handlePreviewClinicalData(scope.row)" />
<!-- 质控后编辑 -->
<el-button icon="el-icon-edit" :title="$t('trials:audit:action:Correction')" circle
v-if="isAuditToEdit" @click="handleEditStudy(scope.row)" />
</template>
</el-table-column>
</el-table>
@ -354,7 +357,7 @@
: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')" min-width="160">
<template slot-scope="scope">
<!-- 预览 -->
<el-button icon="el-icon-view" :title="$t('trials:audit:button:nonDicomsPreview')" circle
@ -365,6 +368,9 @@
<el-button icon="el-icon-edit-outline" :title="$t('trials:audit:button:nonDicomsEdit')" circle
:disabled="isAudit || SecondReviewState > 0"
@click.native.prevent="handleEditNoneDicomInfo(scope.row)" />
<!-- 质控后编辑 -->
<el-button icon="el-icon-edit" :title="$t('trials:audit:action:Correction')" circle
v-if="isAuditToEdit" @click="handleEditNoneDicomInfo(scope.row)" />
</template>
</el-table-column>
</el-table>
@ -633,18 +639,28 @@
</el-checkbox-group>
</el-form-item>
<!-- 序列数量 -->
<el-form-item :label="$t('trials:audit:table:seriesCount')">
<el-form-item :label="$t('trials:audit:table:seriesCount')" v-if="!isAuditToEdit">
<el-input v-model="studyForm.SeriesCount" disabled />
</el-form-item>
<!-- 图像数量 -->
<el-form-item v-if="studyForm.InstanceCount" :label="$t('trials:audit:table:instanceCount')">
<el-form-item v-if="studyForm.InstanceCount && !isAuditToEdit"
:label="$t('trials:audit:table:instanceCount')">
<el-input v-model="studyForm.InstanceCount" disabled />
</el-form-item>
<!-- 检查日期 -->
<el-form-item :label="$t('trials:audit:table:studyDate')">
<el-form-item :label="$t('trials:audit:table:studyDate')" v-if="!isAuditToEdit">
<el-date-picker v-model="studyForm.StudyTime" disabled type="date" value-format="yyyy-MM-dd"
format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
<!-- 修改原因 -->
<el-form-item v-if="isAuditToEdit" :label="$t('trials:audit:table:Reason')" prop="ModifyReason" :rules="[
{
required: true,
message: $t('common:ruleMessage:specify'),
trigger: 'blur',
}]">
<el-input v-model="studyForm.ModifyReason" type="textarea" />
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
@ -730,10 +746,29 @@
</el-checkbox-group>
</el-form-item>
<!-- 检查日期 -->
<el-form-item :label="$t('trials:audit:table:nonDicomsStudyDate')" prop="ImageDate">
<el-form-item :label="$t('trials:audit:table:nonDicomsStudyDate')" prop="ImageDate" :rules="[
{
required: true,
message: $t('common:ruleMessage:specify'),
trigger: 'blur',
}]" v-if="isAuditToEdit">
<el-date-picker v-model="noneDicomForm.ImageDate" type="date" :picker-options="pickerOption"
value-format="yyyy-MM-dd" format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
<!-- 检查日期 -->
<el-form-item :label="$t('trials:audit:table:nonDicomsStudyDate')" prop="ImageDate" v-else>
<el-date-picker v-model="noneDicomForm.ImageDate" disabled type="date" :picker-options="pickerOption"
value-format="yyyy-MM-dd" format="yyyy-MM-dd" style="width: 100%" />
</el-form-item>
<!-- 修改原因 -->
<el-form-item v-if="isAuditToEdit" :label="$t('trials:audit:table:Reason')" prop="ModifyReason" :rules="[
{
required: true,
message: $t('common:ruleMessage:specify'),
trigger: 'blur',
}]">
<el-input v-model="noneDicomForm.ModifyReason" type="textarea" />
</el-form-item>
</el-form>
</div>
<div slot="footer" class="dialog-footer">
@ -882,7 +917,9 @@ import {
updateModality,
getQCChallengeDialogList,
replaceQCTaskActionUser,
getTrialUserRoleList
getTrialUserRoleList,
updateNoneDicomStudy,
updateDicomStudyInfo
} from '@/api/trials'
import { qCPassedOrFailed } from '@/api/trials/visit'
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
@ -924,12 +961,19 @@ export default {
SecondReviewState: {
type: Number,
default: 0,
},
auditorId: {
type: String,
default: ''
}
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
isAuditToEdit() {
return this.isAudit && this.auditorId === this.userId
}
},
data() {
return {
@ -963,6 +1007,7 @@ export default {
BodyPartForEdit: [],
SeriesCount: null,
StudyTime: '',
ModifyReason: ''
},
currentQCRow: {},
isAudit: false, //
@ -981,6 +1026,7 @@ export default {
Modality: '',
ImageDate: '',
StudyName: '',
ModifyReason: ''
},
subjectClinicalData: {},
moment,
@ -1035,7 +1081,8 @@ export default {
secondReviewList: [],
secondReviewActiveName: null,
SecondReviewTime: '',
IsSecondPass: false
IsSecondPass: false,
userId: zzSessionStorage.getItem('userId'),
}
},
async mounted() {
@ -1935,7 +1982,17 @@ export default {
//
closeSignDialog(isSign, signInfo) {
if (isSign) {
this.setQCStatus(signInfo)
if (this.isAuditToEdit) {
if (this.editStudyInfoVisible) {
// dicom
this.updateDicomStudyInfo(signInfo)
} else if (this.editNoneDicomVisible) {
// dicom
this.updateNoneDicomStudy(signInfo)
}
} else {
this.setQCStatus(signInfo)
}
} else {
this.signVisible = false
}
@ -2045,6 +2102,7 @@ export default {
this.$set(this.studyForm, 'Modality', row.ModalityForEdit)
// this.studyForm.Modality = row.ModalityForEdit
this.studyForm.BodyPartForEdit = bodyPart
this.$set(this.studyForm, 'ModifyReason', '')
},
// /
handleUpdateStudyInfo() {
@ -2061,20 +2119,58 @@ export default {
bodyPart: this.studyForm.BodyPart,
StudyName: this.studyForm.StudyName,
}
updateModality(this.data.TrialId, params)
.then((res) => {
this.btnLoading = false
if (res.IsSuccess) {
this.getStudyInfo()
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.editStudyInfoVisible = false
}
})
.catch(() => {
this.btnLoading = false
})
if (this.isAuditToEdit) {
const { CorrectImageExaminationInformation } = const_.processSignature
this.signCode = CorrectImageExaminationInformation
this.signVisible = true
} else {
updateModality(this.data.TrialId, params)
.then((res) => {
this.btnLoading = false
if (res.IsSuccess) {
this.getStudyInfo()
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.editStudyInfoVisible = false
}
})
.catch(() => {
this.btnLoading = false
})
}
})
},
// dicom
async updateDicomStudyInfo(signInfo) {
try {
this.loading = true
let data = {
data: {
Id: this.studyForm.StudyId,
SubjectVisitId: this.data.Id,
StudyName: this.studyForm.StudyName,
ModifyReason: this.studyForm.ModifyReason,
Modality: this.studyForm.Modality,
BodyPart: this.studyForm.BodyPart,
},
signInfo
}
let res = await updateDicomStudyInfo(data)
this.loading = false
this.btnLoading = false
this.signVisible = false
if (res.IsSuccess) {
this.getStudyInfo()
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.editStudyInfoVisible = false
}
} catch (err) {
console.log(err)
this.btnLoading = false
this.loading = false
this.signVisible = false
}
},
//
refreshList() {
//
@ -2101,6 +2197,7 @@ export default {
this.noneDicomForm.Modality = Modality
this.noneDicomForm.ImageDate = ImageDate
this.noneDicomForm.BodyParts = BodyPart.split(', ')
this.noneDicomForm.ModifyReason = null
this.editNoneDicomVisible = true
},
// Dicom/
@ -2113,20 +2210,57 @@ export default {
this.noneDicomForm.TrialSiteId = this.data.TrialSiteId
this.noneDicomForm.SubjectId = this.data.SubjectId
this.noneDicomForm.SubjectVisitId = this.data.Id
addOrUpdateNoneDicomStudy(this.noneDicomForm)
.then((res) => {
this.btnLoading = false
if (res.IsSuccess) {
this.getNoneDicomList()
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.editNoneDicomVisible = false
}
})
.catch(() => {
this.btnLoading = false
})
if (this.isAuditToEdit) {
const { CorrectImageExaminationInformation } = const_.processSignature
this.signCode = CorrectImageExaminationInformation
this.signVisible = true
} else {
addOrUpdateNoneDicomStudy(this.noneDicomForm)
.then((res) => {
this.btnLoading = false
if (res.IsSuccess) {
this.getNoneDicomList()
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.editNoneDicomVisible = false
}
})
.catch(() => {
this.btnLoading = false
})
}
})
},
// dicom
async updateNoneDicomStudy(signInfo) {
try {
this.loading = true
let data = {
data: {
Id: this.noneDicomForm.Id,
SubjectVisitId: this.data.Id,
StudyName: this.noneDicomForm.StudyName,
ModifyReason: this.noneDicomForm.ModifyReason,
Modality: this.noneDicomForm.Modality,
BodyPart: this.noneDicomForm.BodyParts.join(', '),
},
signInfo
}
let res = await updateNoneDicomStudy(data)
this.loading = false
this.btnLoading = false
this.signVisible = false
if (res.IsSuccess) {
this.getNoneDicomList()
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.editNoneDicomVisible = false
}
} catch (err) {
console.log(err)
this.btnLoading = false
this.loading = false
this.signVisible = false
}
},
// Dicom
getNoneDicomList() {
this.loading = true

View File

@ -478,7 +478,8 @@
<div class="qc-dialog-body">
<quality-assurance v-if="qcVisible" :data="rowData" :disabled="rowData.disabled ? rowData.disabled : false"
:SecondReviewState="rowData.SecondReviewState" :q-type="rowData.qcType ? rowData.qcType : 1"
@getList="getList" @nextTask="nextTask" @openManuals="openManuals" @close="qcVisible = false" />
:auditorId="auditorId" @getList="getList" @nextTask="nextTask" @openManuals="openManuals"
@close="qcVisible = false" />
</div>
</el-dialog>
<!-- 手册 -->
@ -692,12 +693,18 @@ export default {
isFullscreen: false,
timeList: [],
exportLoading: false,
auditorId: null
}
},
watch: {
list(val) {
this.doLayout()
},
qcVisible() {
if (!this.qcVisible) {
this.auditorId = null
}
}
},
mounted() {
this.query = this.$route.query
@ -889,12 +896,14 @@ export default {
this.rowData.disabled = true
this.rowData.qcType = 1
this.qcVisible = true
this.auditorId = row.PreliminaryAuditUserId
},
handleViewReviewQC(row) {
this.rowData = { ...row }
this.rowData.disabled = true
this.rowData.qcType = 2
this.qcVisible = true
this.auditorId = row.ReviewAuditUserId
},
//
handleViewImages() {