2703 lines
88 KiB
Vue
2703 lines
88 KiB
Vue
<template>
|
||
<div v-loading="loading" class="qa-wrapper">
|
||
<div class="qa-content" style="position: relative">
|
||
<div
|
||
v-if="existsManual"
|
||
style="position: absolute; right: 20px; top: 10px; z-index: 9"
|
||
>
|
||
<el-button type="text" @click="openManuals">{{
|
||
$t('trials:reading:button:handbooks')
|
||
}}</el-button>
|
||
</div>
|
||
<!-- 所有检查信息 -->
|
||
<el-card shadow="hover" style="min-height: 600px">
|
||
<el-tabs v-model="activeName" type="card">
|
||
<!-- DICOM影像 -->
|
||
<el-tab-pane
|
||
v-if="data.DicomStudyCount > 0"
|
||
:label="$t('trials:audit:tab:dicoms')"
|
||
name="dicom"
|
||
>
|
||
<el-row>
|
||
<el-col :span="12">
|
||
<!-- 检查信息 -->
|
||
<h3>{{ $t('trials:audit:title:dicoms') }}</h3>
|
||
</el-col>
|
||
<el-col :span="12">
|
||
<div
|
||
v-show="isHaveFirstGiveMedicineDate"
|
||
style="text-align: right"
|
||
>
|
||
<!-- 访视窗口期 -->
|
||
<h4>
|
||
{{ $t('trials:audit:tip:visitWindow') }}:
|
||
<span v-if="!!baseDate" style="font-weight: normal">
|
||
{{ `${upperLimit}~${lowerLimit}` }}
|
||
</span>
|
||
<!-- 访视基准日期或窗口未设置 -->
|
||
<span v-else>{{
|
||
$t('trials:audit:tip:visitWindowNotSet')
|
||
}}</span>
|
||
</h4>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
<div style="text-align: right; position: relative">
|
||
<!-- <div
|
||
class="uploadTip"
|
||
style="position: absolute; top: 0; left: 10px"
|
||
>
|
||
{{ $store.state.trials.uploadTip }}
|
||
</div> -->
|
||
<el-tooltip
|
||
v-if="
|
||
$store.state.trials.config.IsSupportQCDownloadImage &&
|
||
!hasPermi(['role:spm'])
|
||
"
|
||
:content="$t('trials:download:tip:message')"
|
||
placement="top-end"
|
||
effect="light"
|
||
>
|
||
<i class="el-icon-warning-outline" style="font-size: 18px"></i>
|
||
</el-tooltip>
|
||
<!-- 下载所有影像 -->
|
||
<el-button
|
||
v-if="
|
||
$store.state.trials.config.IsSupportQCDownloadImage &&
|
||
!hasPermi(['role:spm'])
|
||
"
|
||
:loading="downloading"
|
||
:disabled="selectTableDicom.length <= 0"
|
||
size="small"
|
||
type="primary"
|
||
style="margin-left: 10px"
|
||
@click="getCRCUploadedStudyInfo('dicom')"
|
||
>
|
||
{{ $t('trials:audit:button:downLoadAllDiocms') }}
|
||
</el-button>
|
||
<!-- 预览所有影像 -->
|
||
<el-button
|
||
size="small"
|
||
type="primary"
|
||
style="margin-left: 10px"
|
||
@click="handleViewImages"
|
||
>
|
||
{{ $t('trials:audit:button:previewAllDiocms') }}
|
||
</el-button>
|
||
<!-- 预览阅片影像 -->
|
||
<el-button
|
||
size="small"
|
||
type="primary"
|
||
style="margin-left: 10px"
|
||
@click="handleViewReadingImages"
|
||
>
|
||
{{ $t('trials:audit:button:previewReadingDiocms') }}
|
||
</el-button>
|
||
</div>
|
||
<el-table
|
||
:data="studyList"
|
||
:row-class-name="tableRowClassName"
|
||
@selection-change="handleSelectionChangeDicom"
|
||
:default-sort="{ prop: 'UploadedTime', order: 'ascending' }"
|
||
>
|
||
<el-table-column type="selection" width="55"> </el-table-column>
|
||
<!-- 检查编号 -->
|
||
<el-table-column
|
||
prop="StudyCode"
|
||
:label="$t('trials:audit:table:studyId')"
|
||
sortable
|
||
/>
|
||
<!-- 检查名称 -->
|
||
<el-table-column
|
||
prop="StudyName"
|
||
v-if="relationInfo.IsShowStudyName"
|
||
:label="$t('trials:audit:table:StudyName')"
|
||
sortable
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-tooltip
|
||
class="item"
|
||
effect="dark"
|
||
:content="$t('trials:audit:message:noStudyName')"
|
||
placement="bottom"
|
||
v-if="!scope.row.StudyName"
|
||
>
|
||
<i
|
||
class="el-icon-warning"
|
||
style="color: #f44336; font-size: 16px"
|
||
/>
|
||
</el-tooltip>
|
||
<span v-else>{{ scope.row.StudyName }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 检查类型 -->
|
||
<el-table-column
|
||
prop="ModalityForEdit"
|
||
:label="$t('trials:audit:table:modality')"
|
||
sortable
|
||
/>
|
||
<!-- 检查类型 -->
|
||
<el-table-column
|
||
prop="Modalities"
|
||
:label="$t('trials:audit:table:modality1')"
|
||
sortable
|
||
/>
|
||
<!-- 检查部位 -->
|
||
<el-table-column
|
||
prop="BodyPartForEdit"
|
||
:label="$t('trials:audit:table:bodyPart')"
|
||
sortable
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-tooltip
|
||
class="item"
|
||
effect="dark"
|
||
:content="$t('trials:audit:message:noBodyPartForEdit')"
|
||
placement="bottom"
|
||
v-if="!scope.row.BodyPartForEdit"
|
||
>
|
||
<i
|
||
class="el-icon-warning"
|
||
style="color: #f44336; font-size: 16px"
|
||
/>
|
||
</el-tooltip>
|
||
<span v-else>{{
|
||
getBodyPart(scope.row.BodyPartForEdit)
|
||
}}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 序列数量 -->
|
||
<el-table-column
|
||
prop="SeriesCount"
|
||
:label="$t('trials:audit:table:seriesCount')"
|
||
sortable
|
||
/>
|
||
<!-- 图像数量 -->
|
||
<el-table-column
|
||
prop="InstanceCount"
|
||
:label="$t('trials:audit:table:instanceCount')"
|
||
sortable
|
||
/>
|
||
<!-- 检查日期 -->
|
||
<el-table-column
|
||
prop="StudyTime"
|
||
:label="$t('trials:audit:table:studyDate')"
|
||
sortable
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-tooltip
|
||
class="item"
|
||
effect="dark"
|
||
:content="$t('trials:audit:message:qsOverWindow')"
|
||
placement="bottom"
|
||
>
|
||
<i
|
||
v-if="
|
||
isHaveFirstGiveMedicineDate &&
|
||
!!baseDate &&
|
||
scope.row.StudyTime &&
|
||
(moment(scope.row.StudyTime).format('YYYY-MM-DD') >
|
||
lowerLimit ||
|
||
moment(scope.row.StudyTime).format('YYYY-MM-DD') <
|
||
upperLimit)
|
||
"
|
||
class="el-icon-warning"
|
||
style="color: #f44336; font-size: 16px"
|
||
/>
|
||
</el-tooltip>
|
||
|
||
<span>{{
|
||
scope.row.StudyTime
|
||
? moment(scope.row.StudyTime).format('YYYY-MM-DD')
|
||
: ''
|
||
}}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 更新时间 -->
|
||
<el-table-column
|
||
prop="UpdateTime"
|
||
:label="$t('trials:audit:table:seriesOfUpdateTime')"
|
||
min-width="120"
|
||
sortable
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 上传时间 -->
|
||
<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')">
|
||
<template slot-scope="scope">
|
||
<!-- 预览 -->
|
||
<el-button
|
||
icon="el-icon-view"
|
||
:title="$t('trials:audit:action:preview')"
|
||
circle
|
||
:disabled="scope.row.IsDeleted"
|
||
@click="handlePreviewStudy(scope.row)"
|
||
/>
|
||
<!-- 编辑 -->
|
||
<el-button
|
||
icon="el-icon-edit-outline"
|
||
:title="$t('trials:audit:action:edit')"
|
||
circle
|
||
:disabled="isAudit || scope.row.IsDeleted"
|
||
@click="handleEditStudy(scope.row)"
|
||
/>
|
||
<!-- 预览PET-CT数据 -->
|
||
<el-button
|
||
type="primary"
|
||
icon="el-icon-document tip-i"
|
||
:title="$t('trials:audit:tab:clinicalData')"
|
||
v-if="
|
||
['PT、CT', 'CT、PT', 'PET-CT'].includes(
|
||
scope.row.Modalities
|
||
) && IsHaveStudyClinicalData
|
||
"
|
||
circle
|
||
:disabled="scope.row.IsDeleted"
|
||
@click="handlePreviewClinicalData(scope.row)"
|
||
/>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<!-- 序列信息 -->
|
||
<h3>{{ $t('trials:audit:title:series') }}</h3>
|
||
<el-table
|
||
:data="seriesList"
|
||
:row-class-name="tableRowClassName"
|
||
:default-sort="{ prop: 'CreateTime', order: 'ascending' }"
|
||
>
|
||
<!-- 序列号 -->
|
||
<el-table-column
|
||
prop="SeriesNumber"
|
||
:label="$t('trials:audit:table:seriesId')"
|
||
sortable
|
||
/>
|
||
<!-- 检查编号 -->
|
||
<el-table-column
|
||
prop="StudyCode"
|
||
:label="$t('trials:audit:table:seriesOfStudyId')"
|
||
sortable
|
||
/>
|
||
<!-- 检查类型 -->
|
||
<el-table-column
|
||
prop="Modality"
|
||
:label="$t('trials:audit:table:seriesModality')"
|
||
sortable
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 图像数量 -->
|
||
<el-table-column
|
||
prop="InstanceCount"
|
||
:label="$t('trials:audit:table:seriesOfInstanceCount')"
|
||
sortable
|
||
/>
|
||
<!-- 检查日期 -->
|
||
<el-table-column
|
||
prop="SeriesTime"
|
||
:label="$t('trials:audit:table:seriesOfStudyDate')"
|
||
sortable
|
||
show-overflow-tooltip
|
||
>
|
||
<template slot-scope="scope">
|
||
{{
|
||
scope.row.StudyTime
|
||
? moment(scope.row.StudyTime).format('YYYY-MM-DD')
|
||
: ''
|
||
}}
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 更新时间 -->
|
||
<el-table-column
|
||
prop="UpdateTime"
|
||
:label="$t('trials:audit:table:seriesOfUpdateTime')"
|
||
sortable
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 上传时间 -->
|
||
<el-table-column
|
||
prop="CreateTime"
|
||
:label="$t('trials:audit:table:seriesOfUploadedDate')"
|
||
sortable
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 是否阅片 -->
|
||
<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)"
|
||
: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)"
|
||
:active-text="$fd('YesOrNo', true)"
|
||
:inactive-text="$fd('YesOrNo', false)"
|
||
/>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column :label="$t('common:action:action')">
|
||
<template slot-scope="scope">
|
||
<!-- 预览 -->
|
||
<el-button
|
||
icon="el-icon-view"
|
||
:title="$t('trials:audit:action:seriesPreview')"
|
||
circle
|
||
:disabled="scope.row.IsDeleted"
|
||
@click="handlePreviewInstance(scope.row)"
|
||
/>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
<!-- 非DICOM影像 -->
|
||
<el-tab-pane
|
||
v-if="data.NoneDicomStudyCount > 0"
|
||
:label="$t('trials:audit:tab:nonDicoms')"
|
||
name="none-dicom"
|
||
>
|
||
<el-row>
|
||
<!-- 检查信息 -->
|
||
<el-col :span="12"
|
||
><h3>{{ $t('trials:audit:title:nonDicomsTitle') }}</h3></el-col
|
||
>
|
||
<el-col :span="12">
|
||
<div
|
||
v-show="isHaveFirstGiveMedicineDate"
|
||
style="text-align: right"
|
||
>
|
||
<!-- 访视窗口期 -->
|
||
<h4>
|
||
{{ $t('trials:audit:tip:nonDicomsVisitWindow') }}:
|
||
<span v-if="!!baseDate" style="font-weight: normal">
|
||
{{ `${upperLimit}~${lowerLimit}` }}
|
||
</span>
|
||
<!-- 访视基准日期或窗口未设置 -->
|
||
<span v-else>{{
|
||
$t('trials:audit:tip:visitWindowNotSet')
|
||
}}</span>
|
||
</h4>
|
||
</div>
|
||
</el-col>
|
||
</el-row>
|
||
<div style="text-align: right; position: relative">
|
||
<!-- <div
|
||
class="uploadTip"
|
||
style="position: absolute; top: 0; left: 10px"
|
||
>
|
||
{{ $store.state.trials.uploadTip }}
|
||
</div> -->
|
||
<el-tooltip
|
||
v-if="
|
||
$store.state.trials.config.IsSupportQCDownloadImage &&
|
||
!hasPermi(['role:spm'])
|
||
"
|
||
:content="$t('trials:download:tip:message')"
|
||
placement="top-end"
|
||
effect="light"
|
||
>
|
||
<i class="el-icon-warning-outline" style="font-size: 18px"></i>
|
||
</el-tooltip>
|
||
<!-- 下载所有影像 -->
|
||
<el-button
|
||
v-if="
|
||
$store.state.trials.config.IsSupportQCDownloadImage &&
|
||
!hasPermi(['role:spm'])
|
||
"
|
||
:loading="downloading"
|
||
:disabled="selectTableNonedicom.length <= 0"
|
||
size="small"
|
||
type="primary"
|
||
style="margin-left: 10px"
|
||
@click="getCRCUploadedStudyInfo('noneDicom')"
|
||
>
|
||
{{ $t('trials:audit:button:downLoadAllNonDiocms') }}
|
||
</el-button>
|
||
<!-- 预览 -->
|
||
<el-button
|
||
size="small"
|
||
:disabled="noneDicomStudyList.length === 0"
|
||
type="primary"
|
||
style="margin-left: 10px"
|
||
@click="handleViewAllNoneDicoms"
|
||
>
|
||
{{ $t('trials:audit:tip:nonDicomsPreviewAll') }}
|
||
</el-button>
|
||
</div>
|
||
<el-table
|
||
:data="noneDicomStudyList"
|
||
@selection-change="handleSelectionChangeNonedicom"
|
||
:default-sort="{ prop: 'CreateTime', order: 'ascending' }"
|
||
>
|
||
<el-table-column type="selection" width="55"> </el-table-column>
|
||
<!-- 检查编号 -->
|
||
<el-table-column
|
||
prop="CodeView"
|
||
:label="$t('trials:audit:table:nonDicomsStudyId')"
|
||
sortable
|
||
/>
|
||
<!-- 检查名称 -->
|
||
<el-table-column
|
||
prop="StudyName"
|
||
v-if="relationInfo.IsShowStudyName"
|
||
:label="$t('trials:audit:table:StudyName')"
|
||
sortable
|
||
/>
|
||
<!-- 检查类型 -->
|
||
<el-table-column
|
||
prop="Modality"
|
||
:label="$t('trials:audit:table:nonDicomsModality')"
|
||
sortable
|
||
/>
|
||
<!-- 检查部位 -->
|
||
<el-table-column
|
||
prop="BodyPart"
|
||
:label="$t('trials:audit:table:nonDicomsBodypart')"
|
||
sortable
|
||
>
|
||
<template slot-scope="scope">
|
||
{{ getBodyPart(scope.row.BodyPart) }}
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 文件 -->
|
||
<el-table-column
|
||
prop="FileCount"
|
||
:label="$t('trials:audit:table:nonDicomsFileCount')"
|
||
sortable
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-popover
|
||
v-if="scope.row.FileCount"
|
||
trigger="click"
|
||
placement="bottom"
|
||
>
|
||
<el-table
|
||
:data="scope.row.NoneDicomStudyFileList"
|
||
height="300"
|
||
size="small"
|
||
>
|
||
<!-- 文件名称 -->
|
||
<el-table-column
|
||
prop="FileName"
|
||
:label="$t('trials:audit:table:nonDicomsFileName')"
|
||
width="200"
|
||
/>
|
||
<el-table-column
|
||
prop="FileSize"
|
||
:label="$t('trials:audit:table:nonDicomsFileSize')"
|
||
width="100"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span>{{
|
||
scope.row.FileSize && scope.row.FileSize > 0
|
||
? `${(scope.row.FileSize / 1024 / 1024).toFixed(
|
||
2
|
||
)}MB`
|
||
: 0
|
||
}}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column
|
||
:label="$t('common:action:action')"
|
||
width="120"
|
||
>
|
||
<template slot-scope="files">
|
||
<!-- 预览 -->
|
||
<viewer
|
||
:ref="files.row.FullFilePath"
|
||
style="margin: 0 10px"
|
||
:images="[
|
||
`${OSSclientConfig.basePath}${files.row.FullFilePath}`,
|
||
]"
|
||
>
|
||
<el-button
|
||
type="text"
|
||
:disabled="
|
||
files.row.FileType &&
|
||
files.row.FileType.indexOf('zip') >= 0
|
||
"
|
||
@click.native.prevent="previewFile(files.row)"
|
||
>
|
||
{{ $t('trials:audit:button:nonDicomsPreview') }}
|
||
</el-button>
|
||
<img
|
||
v-show="false"
|
||
crossorigin="anonymous"
|
||
:src="`${OSSclientConfig.basePath}${files.row.FullFilePath}`"
|
||
alt="Image"
|
||
/>
|
||
</viewer>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
<div slot="reference" class="name-wrapper">
|
||
<el-button type="text">
|
||
{{ scope.row.FileCount }}
|
||
</el-button>
|
||
</div>
|
||
</el-popover>
|
||
<span v-else>{{ scope.row.FileCount }}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 检查日期 -->
|
||
<el-table-column
|
||
prop="ImageDate"
|
||
:label="$t('trials:audit:table:nonDicomsStudyDate')"
|
||
sortable
|
||
>
|
||
<template slot-scope="scope">
|
||
<i
|
||
v-if="
|
||
isHaveFirstGiveMedicineDate &&
|
||
!!baseDate &&
|
||
scope.row.ImageDate &&
|
||
(moment(scope.row.ImageDate).format('YYYY-MM-DD') >
|
||
lowerLimit ||
|
||
moment(scope.row.ImageDate).format('YYYY-MM-DD') <
|
||
upperLimit)
|
||
"
|
||
class="el-icon-warning"
|
||
style="color: #f44336; font-size: 16px"
|
||
/>
|
||
<span>{{
|
||
moment(scope.row.ImageDate).format('YYYY-MM-DD')
|
||
}}</span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 更新时间 -->
|
||
<el-table-column
|
||
prop="UpdateTime"
|
||
:label="$t('trials:audit:table:nonDicomsUpdateTime')"
|
||
sortable
|
||
/>
|
||
<!-- 创建时间 -->
|
||
<el-table-column
|
||
prop="CreateTime"
|
||
:label="$t('trials:audit:table:nonDicomsCreateTime')"
|
||
sortable
|
||
/>
|
||
<el-table-column :label="$t('common:action:action')">
|
||
<template slot-scope="scope">
|
||
<!-- 预览 -->
|
||
<el-button
|
||
icon="el-icon-view"
|
||
:title="$t('trials:audit:button:nonDicomsPreview')"
|
||
circle
|
||
:disabled="scope.row.FileCount === 0"
|
||
@click.native.prevent="
|
||
handlePreviewNoneDicomFiles(scope.row)
|
||
"
|
||
/>
|
||
<!-- 编辑 -->
|
||
<el-button
|
||
icon="el-icon-edit-outline"
|
||
:title="$t('trials:audit:button:nonDicomsEdit')"
|
||
circle
|
||
:disabled="isAudit"
|
||
@click.native.prevent="handleEditNoneDicomInfo(scope.row)"
|
||
/>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-tab-pane>
|
||
<!-- 临床数据 -->
|
||
<!-- data.IsBaseLine && relationInfo.TrialClinicalInformationTransmissionEnum*1>0 && data.IsHaveClinicalData -->
|
||
<el-tab-pane
|
||
v-if="data.IsHaveClinicalData"
|
||
:label="$t('trials:audit:tab:clinicalData')"
|
||
name="clinical-data"
|
||
>
|
||
<ClinicalData
|
||
v-if="Object.keys(subjectClinicalData).length > 0"
|
||
:data="data"
|
||
style="margin-top: 5px"
|
||
:subject-clinical-data="subjectClinicalData"
|
||
:enum-type="
|
||
relationInfo.TrialClinicalInformationTransmissionEnum * 1
|
||
"
|
||
:subject-visit-id="data.Id"
|
||
:is-audit="isAudit"
|
||
:subject-id="data.SubjectId"
|
||
/>
|
||
</el-tab-pane>
|
||
</el-tabs>
|
||
</el-card>
|
||
|
||
<!-- 审核问题 -->
|
||
<!-- select/input/textarea/radio -->
|
||
<el-card shadow="hover" style="margin-top: 10px">
|
||
<!-- 审核问题 -->
|
||
<h3>{{ $t('trials:audit:title:questions') }}</h3>
|
||
<div v-if="qCQuestionAnswerList.length > 0" style="overflow-y: auto">
|
||
<QuestionForm
|
||
ref="questions"
|
||
:trial-id="trialId"
|
||
:subject-visit-id="data.Id"
|
||
:qc-process-enum="data.QCProcessEnum"
|
||
:current-q-c-enum="currentQCType"
|
||
:answers="qCQuestionAnswerList"
|
||
:is-audit="isAudit"
|
||
/>
|
||
</div>
|
||
<!-- 暂无数据 -->
|
||
<h3 v-else>{{ $t('trials:audit:message:noData') }}</h3>
|
||
</el-card>
|
||
|
||
<!-- 发起质疑 -->
|
||
<el-dialog
|
||
v-if="qcVisible"
|
||
:title="$t('trials:audit:dialogTitle:question')"
|
||
:visible.sync="qcVisible"
|
||
:close-on-click-modal="false"
|
||
append-to-body
|
||
custom-class="base-dialog-wrapper"
|
||
width="1000px"
|
||
>
|
||
<div
|
||
style="
|
||
padding: 10px;
|
||
border: 1px solid #e0e0e0;
|
||
max-height: 650px;
|
||
overflow-y: auto;
|
||
"
|
||
>
|
||
<el-form
|
||
v-if="qcVisible"
|
||
ref="qcForm"
|
||
:model="qcForm"
|
||
label-width="180px"
|
||
size="small"
|
||
>
|
||
<el-form-item :label="$t('trials:audit:form:questionContent')">
|
||
<!-- :header-row-style="{display:'none'}" -->
|
||
<el-table :data="qcForm.qcContent" style="width: 100%">
|
||
<el-table-column prop="isSelect" label="" width="40">
|
||
<template slot-scope="scope">
|
||
<el-checkbox v-model="scope.row.isSelect" />
|
||
</template>
|
||
</el-table-column>
|
||
<el-table-column prop="keyName" label="" width="180">
|
||
<template slot-scope="scope">
|
||
<span v-html="scope.row.keyName"></span>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 问题总结 -->
|
||
<el-table-column
|
||
prop="keyValue"
|
||
:label="$t('trials:audit:form:questionSummary')"
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-input
|
||
v-show="scope.row.keyValue || scope.row.isSelect"
|
||
v-model="scope.row.keyValue"
|
||
type="textarea"
|
||
:rows="4"
|
||
size="mini"
|
||
/>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 行动事项 -->
|
||
<el-table-column
|
||
prop="ActionContent"
|
||
:label="$t('trials:audit:form:actionMatters')"
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-input
|
||
v-show="scope.row.actionContent || scope.row.isSelect"
|
||
v-model="scope.row.actionContent"
|
||
type="textarea"
|
||
:rows="4"
|
||
size="mini"
|
||
/>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-form-item>
|
||
<el-form-item :label="$t('trials:audit:form:questionDeadline')">
|
||
<el-date-picker
|
||
v-model="qcForm.deadlineTime"
|
||
value-format="yyyy-MM-dd HH:mm:ss"
|
||
type="datetime"
|
||
size="small"
|
||
clearable
|
||
default-time="23:59:59"
|
||
style="width: 100%"
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
<div slot="footer" class="dialog-footer">
|
||
<!-- 取消 -->
|
||
<el-button
|
||
:disabled="btnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="qcVisible = false"
|
||
>
|
||
{{ $t('common:button:cancel') }}
|
||
</el-button>
|
||
<!-- 保存 -->
|
||
<el-button
|
||
size="small"
|
||
type="primary"
|
||
:loading="btnLoading"
|
||
@click="handleSaveQC"
|
||
>
|
||
{{ $t('common:button:save') }}
|
||
</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- 历史质疑 -->
|
||
<el-dialog
|
||
v-if="historyVisible"
|
||
:visible.sync="historyVisible"
|
||
:close-on-click-modal="false"
|
||
custom-class="base-dialog-wrapper"
|
||
append-to-body
|
||
width="80%"
|
||
:title="$t('trials:audit:dialogTitle:historicalQuestions')"
|
||
>
|
||
<div style="text-align: right">
|
||
<el-button
|
||
icon="el-icon-refresh-left"
|
||
circle
|
||
:title="$t('trials:audit:button:refreshHistoryQs')"
|
||
@click="getHistoryInfo"
|
||
/>
|
||
</div>
|
||
<el-table
|
||
v-loading="historyLoading"
|
||
:data="historyList"
|
||
style="width: 100%"
|
||
height="500"
|
||
>
|
||
<!-- 质疑编号 -->
|
||
<el-table-column
|
||
prop="ChallengeCode"
|
||
:label="$t('trials:qcQuality:table:challengeCode')"
|
||
width="100"
|
||
show-overflow-tooltip
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-button
|
||
:style="{ color: scope.row.IsClosed ? '' : 'red' }"
|
||
type="text"
|
||
@click="handleReply(scope.row)"
|
||
>{{ scope.row.ChallengeCode }}</el-button
|
||
>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 质疑状态 -->
|
||
<el-table-column
|
||
prop="IsClosed"
|
||
:label="$t('trials:qcQuality:table:isClosed')"
|
||
width="80"
|
||
show-overflow-tooltip
|
||
>
|
||
<template slot-scope="scope">
|
||
{{ $fd('IsClosed', scope.row.IsClosed) }}
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 创建时间 -->
|
||
<el-table-column
|
||
prop="CreateTime"
|
||
:label="$t('trials:qcQuality:table:createTime')"
|
||
width="150"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 创建人 -->
|
||
<el-table-column
|
||
prop="CreateUserName"
|
||
:label="$t('trials:qcQuality:table:organizer')"
|
||
width="100"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 领取人 -->
|
||
<el-table-column
|
||
prop="CurrentActionUserName"
|
||
:label="$t('trials:qcCheck:table:crrentUser')"
|
||
width="100"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 最新消息时间 -->
|
||
<el-table-column
|
||
prop="LatestMsgTime"
|
||
:label="$t('trials:qcQuality:table:latestMsgTime')"
|
||
width="200"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 重传状态 -->
|
||
<el-table-column
|
||
prop="ReuploadEnum"
|
||
:label="$t('trials:qcQuality:table:reUploadStatus')"
|
||
show-overflow-tooltip
|
||
width="180"
|
||
sortable="custom"
|
||
>
|
||
<template slot-scope="scope">
|
||
<span v-if="scope.row.ReuploadEnum === 0">--</span>
|
||
<el-tag v-else-if="scope.row.ReuploadEnum === 1" type="danger">{{
|
||
$fd('ReuploadEnum', scope.row.ReuploadEnum)
|
||
}}</el-tag>
|
||
<el-tag v-else-if="scope.row.ReuploadEnum === 2" type="warning">{{
|
||
$fd('ReuploadEnum', scope.row.ReuploadEnum)
|
||
}}</el-tag>
|
||
<el-tag v-else-if="scope.row.ReuploadEnum === 3" type="primary">{{
|
||
$fd('ReuploadEnum', scope.row.ReuploadEnum)
|
||
}}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 重传完成时间 -->
|
||
<el-table-column
|
||
prop="ReUploadedTime"
|
||
:label="$t('trials:qcQuality:table:reUploadTime')"
|
||
show-overflow-tooltip
|
||
width="260"
|
||
sortable="custom"
|
||
/>
|
||
<!-- 处理截止日期 -->
|
||
<el-table-column
|
||
prop="DeadlineTime"
|
||
:label="$t('trials:qcQuality:table:deadline')"
|
||
width="160"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 是否超限 -->
|
||
<el-table-column
|
||
prop="IsOverTime"
|
||
:label="$t('trials:qcQuality:table:isOverTime')"
|
||
width="160"
|
||
show-overflow-tooltip
|
||
>
|
||
<template slot-scope="scope">
|
||
{{ $fd('YesOrNo', scope.row.IsOverTime) }}
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 关闭时间 -->
|
||
<el-table-column
|
||
prop="ClosedTime"
|
||
:label="$t('trials:qcQuality:table:closingTime')"
|
||
min-width="150"
|
||
show-overflow-tooltip
|
||
/>
|
||
<el-table-column
|
||
:label="$t('common:action:action')"
|
||
fixed="right"
|
||
min-width="160"
|
||
>
|
||
<template slot-scope="scope">
|
||
<!-- 回复 -->
|
||
<el-button
|
||
type="text"
|
||
:disabled="scope.row.IsClosed || isAudit"
|
||
@click="handleReply(scope.row)"
|
||
>
|
||
{{ $t('trials:qcQuality:action:reply') }}
|
||
</el-button>
|
||
<!-- 关闭 -->
|
||
<el-button
|
||
type="text"
|
||
:disabled="scope.row.IsClosed || isAudit"
|
||
@click="handleCloseQC(scope.row)"
|
||
>
|
||
{{ $t('trials:qcQuality:action:close') }}
|
||
</el-button>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
</el-dialog>
|
||
|
||
<!-- 质疑记录 -->
|
||
<el-dialog
|
||
v-if="chatVisible"
|
||
:visible.sync="chatVisible"
|
||
:close-on-click-modal="false"
|
||
custom-class="base-dialog-wrapper"
|
||
append-to-body
|
||
width="800px"
|
||
:title="
|
||
$t('trials:qcQuality:dialogTitle:reply') +
|
||
`(${currentQCRow.SubjectCode} ${currentQCRow.VisitName})`
|
||
"
|
||
>
|
||
<chat-form
|
||
:data="currentQCRow"
|
||
:sign-text="relationInfo.TrialImageQCSignText"
|
||
:clinical-enum="relationInfo.ClinicalInformationTransmissionEnum"
|
||
@close="chatVisible = false"
|
||
@getDialogList="getDialogList"
|
||
/>
|
||
</el-dialog>
|
||
|
||
<!-- 更新检查拍片部位信息 -->
|
||
<el-dialog
|
||
v-if="editStudyInfoVisible"
|
||
:title="$t('trials:audit:action:edit')"
|
||
:visible.sync="editStudyInfoVisible"
|
||
:close-on-click-modal="false"
|
||
append-to-body
|
||
custom-class="base-dialog-wrapper"
|
||
width="600px"
|
||
>
|
||
<div
|
||
style="
|
||
padding: 10px;
|
||
border: 1px solid #e0e0e0;
|
||
max-height: 650px;
|
||
overflow-y: auto;
|
||
"
|
||
>
|
||
<el-form ref="studyForm" :model="studyForm" label-width="100px">
|
||
<!-- 检查编号 -->
|
||
<el-form-item :label="$t('trials:audit:table:studyId')">
|
||
<el-input v-model="studyForm.StudyCode" disabled />
|
||
</el-form-item>
|
||
<!-- 检查名称 -->
|
||
<el-form-item
|
||
v-if="relationInfo.IsShowStudyName"
|
||
:label="$t('trials:audit:table:StudyName')"
|
||
prop="StudyName"
|
||
:rules="[
|
||
{
|
||
required: true,
|
||
message: $t('common:ruleMessage:specify'),
|
||
trigger: 'blur',
|
||
},
|
||
]"
|
||
>
|
||
<el-radio-group v-model="studyForm.StudyName">
|
||
<template v-for="m in relationInfo.StudyNameList">
|
||
<el-radio
|
||
v-if="m.IsChoose"
|
||
:key="m.Name"
|
||
:label="isEN ? m.EnName : m.Name"
|
||
style="line-height: 40px"
|
||
/>
|
||
</template>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<!-- 检查类型 -->
|
||
<el-form-item
|
||
v-if="studyForm.IsDicomData"
|
||
:label="$t('trials:audit:table:modality')"
|
||
>
|
||
<el-input v-model="studyForm.Modalities" disabled />
|
||
</el-form-item>
|
||
<!-- 检查类型 -->
|
||
<el-form-item
|
||
v-else
|
||
:label="$t('trials:audit:table:modality')"
|
||
prop="Modalities"
|
||
:rules="[
|
||
{
|
||
required: true,
|
||
message: $t('common:ruleMessage:specify'),
|
||
trigger: 'blur',
|
||
},
|
||
]"
|
||
>
|
||
<el-radio-group v-model="studyForm.Modality">
|
||
<el-radio
|
||
v-for="m in trialModalitys"
|
||
v-show="m !== ''"
|
||
:key="m"
|
||
:label="m"
|
||
style="margin-bottom: 15px"
|
||
/>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<!-- 检查部位 -->
|
||
<el-form-item
|
||
:label="$t('trials:audit:table:bodyPart')"
|
||
prop="BodyPartForEdit"
|
||
:rules="[
|
||
{
|
||
required: true,
|
||
message: $t('common:ruleMessage:specify'),
|
||
trigger: 'blur',
|
||
},
|
||
]"
|
||
>
|
||
<el-checkbox-group v-model="studyForm.BodyPartForEdit">
|
||
<el-checkbox
|
||
v-for="bodyPart in trialBodyPartTypes"
|
||
:key="bodyPart"
|
||
:label="bodyPart"
|
||
>{{
|
||
$fd('Bodypart', bodyPart, 'Code', BodyPart, 'Name')
|
||
}}</el-checkbox
|
||
>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
<!-- 序列数量 -->
|
||
<el-form-item :label="$t('trials:audit:table:seriesCount')">
|
||
<el-input v-model="studyForm.SeriesCount" disabled />
|
||
</el-form-item>
|
||
<!-- 图像数量 -->
|
||
<el-form-item
|
||
v-if="studyForm.InstanceCount"
|
||
: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-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>
|
||
</div>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button
|
||
:disabled="btnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="editStudyInfoVisible = false"
|
||
>
|
||
{{ $t('common:button:cancel') }}
|
||
</el-button>
|
||
<el-button
|
||
:loading="btnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="handleUpdateStudyInfo"
|
||
>
|
||
{{ $t('common:button:save') }}
|
||
</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- 审核签名 -->
|
||
<el-dialog
|
||
v-if="signVisible"
|
||
:visible.sync="signVisible"
|
||
:close-on-click-modal="false"
|
||
width="600px"
|
||
append-to-body
|
||
custom-class="base-dialog-wrapper"
|
||
>
|
||
<div slot="title">
|
||
<span style="font-size: 18px">{{
|
||
$t('common:dialogTitle:sign')
|
||
}}</span>
|
||
<span style="font-size: 12px; margin-left: 5px">{{
|
||
`(${$t('common:label:sign')}${currentUser})`
|
||
}}</span>
|
||
</div>
|
||
<SignForm
|
||
ref="signForm"
|
||
:sign-code-enum="signCode"
|
||
:subject-visit-id="data.Id"
|
||
@closeDialog="closeSignDialog"
|
||
/>
|
||
</el-dialog>
|
||
<!-- 编辑非Dicom文件 -->
|
||
<el-dialog
|
||
v-if="editNoneDicomVisible"
|
||
:title="$t('trials:audit:button:nonDicomsEdit')"
|
||
:visible.sync="editNoneDicomVisible"
|
||
:close-on-click-modal="false"
|
||
append-to-body
|
||
custom-class="base-dialog-wrapper"
|
||
width="600px"
|
||
>
|
||
<div
|
||
style="
|
||
padding: 10px;
|
||
border: 1px solid #e0e0e0;
|
||
max-height: 650px;
|
||
overflow-y: auto;
|
||
"
|
||
>
|
||
<el-form
|
||
ref="noneDicomForm"
|
||
:model="noneDicomForm"
|
||
label-width="100px"
|
||
>
|
||
<!-- 检查编号 -->
|
||
<el-form-item :label="$t('trials:audit:table:nonDicomsStudyId')">
|
||
<el-input v-model="noneDicomForm.CodeView" disabled />
|
||
</el-form-item>
|
||
<!-- 检查名称 -->
|
||
<el-form-item
|
||
v-if="relationInfo.IsShowStudyName"
|
||
:label="$t('trials:audit:table:StudyName')"
|
||
prop="StudyName"
|
||
:rules="[
|
||
{
|
||
required: true,
|
||
message: $t('common:ruleMessage:specify'),
|
||
trigger: 'blur',
|
||
},
|
||
]"
|
||
>
|
||
<el-radio-group v-model="noneDicomForm.StudyName">
|
||
<template v-for="m in relationInfo.StudyNameList">
|
||
<el-radio
|
||
v-if="m.IsChoose"
|
||
:key="m.Name"
|
||
:label="isEN ? m.EnName : m.Name"
|
||
style="line-height: 40px"
|
||
/>
|
||
</template>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<!-- 检查类型 -->
|
||
<el-form-item
|
||
:label="$t('trials:audit:table:nonDicomsModality')"
|
||
prop="Modality"
|
||
:rules="[
|
||
{
|
||
required: true,
|
||
message: $t('common:ruleMessage:specify'),
|
||
trigger: 'blur',
|
||
},
|
||
]"
|
||
>
|
||
<el-radio-group v-model="noneDicomForm.Modality">
|
||
<el-radio
|
||
v-for="m in trialModalitys"
|
||
v-show="m !== ''"
|
||
:key="m"
|
||
:label="m"
|
||
style="margin-bottom: 15px"
|
||
/>
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<!-- 检查部位 -->
|
||
<el-form-item
|
||
:label="$t('trials:audit:table:nonDicomsBodypart')"
|
||
prop="BodyParts"
|
||
:rules="[
|
||
{
|
||
required: true,
|
||
message: $t('common:ruleMessage:specify'),
|
||
trigger: 'blur',
|
||
},
|
||
]"
|
||
>
|
||
<el-checkbox-group v-model="noneDicomForm.BodyParts">
|
||
<el-checkbox
|
||
v-for="bodyPart in trialBodyPartTypes"
|
||
:key="bodyPart"
|
||
:label="bodyPart"
|
||
>{{
|
||
$fd('Bodypart', bodyPart, 'Code', BodyPart, 'Name')
|
||
}}</el-checkbox
|
||
>
|
||
</el-checkbox-group>
|
||
</el-form-item>
|
||
<!-- 检查日期 -->
|
||
<el-form-item
|
||
:label="$t('trials:audit:table:nonDicomsStudyDate')"
|
||
prop="ImageDate"
|
||
>
|
||
<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>
|
||
</div>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button
|
||
:disabled="btnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="editNoneDicomVisible = false"
|
||
>
|
||
{{ $t('common:button:cancel') }}
|
||
</el-button>
|
||
<el-button
|
||
:loading="btnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="handleUpdateNoneDicomInfo"
|
||
>
|
||
{{ $t('common:button:save') }}
|
||
</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
|
||
<!-- 关闭质疑 -->
|
||
<el-dialog
|
||
v-if="closeQuestionVisible"
|
||
:visible.sync="closeQuestionVisible"
|
||
:close-on-click-modal="false"
|
||
append-to-body
|
||
custom-class="base-dialog-wrapper"
|
||
width="600px"
|
||
:title="$t('trials:qcQuality:dialogTitle:closeQuestion')"
|
||
>
|
||
<div
|
||
style="
|
||
padding: 10px;
|
||
border: 1px solid #e0e0e0;
|
||
max-height: 650px;
|
||
overflow-y: auto;
|
||
"
|
||
>
|
||
<el-form
|
||
ref="closeQuestionForm"
|
||
:model="closeQuestionForm"
|
||
size="small"
|
||
label-width="120px"
|
||
>
|
||
<el-form-item
|
||
:label="$t('trials:qcQuality:label:closeReason')"
|
||
prop="Type"
|
||
:rules="[
|
||
{ required: true, message: $t('common:ruleMessage:select') },
|
||
]"
|
||
>
|
||
<el-radio-group v-model="closeQuestionForm.Type">
|
||
<!-- 问题已解决 -->
|
||
<el-radio :label="1">{{
|
||
$t('trials:qcQuality:radio:reason1')
|
||
}}</el-radio>
|
||
<!-- 问题无法解决强制关闭质疑 -->
|
||
<el-radio :label="2">{{
|
||
$t('trials:qcQuality:radio:reason2')
|
||
}}</el-radio>
|
||
<!-- <!– 其他 –>-->
|
||
<!-- <el-radio :label="3">{{ $t('trials:qcQuality:radio:reason3') }}</el-radio>-->
|
||
</el-radio-group>
|
||
</el-form-item>
|
||
<el-form-item
|
||
v-if="closeQuestionForm.Type === 2"
|
||
:label="$t('trials:consistencyCheck:label:closereason')"
|
||
prop="Remake"
|
||
:rules="[
|
||
{ required: true, message: $t('common:ruleMessage:specify') },
|
||
]"
|
||
>
|
||
<el-input
|
||
v-model="closeQuestionForm.Remake"
|
||
type="textarea"
|
||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||
/>
|
||
</el-form-item>
|
||
</el-form>
|
||
</div>
|
||
<div slot="footer" class="dialog-footer">
|
||
<el-button
|
||
:disabled="closeBtnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="closeQuestionVisible = false"
|
||
>
|
||
{{ $t('common:button:cancel') }}
|
||
</el-button>
|
||
<el-button
|
||
:loading="closeBtnLoading"
|
||
size="small"
|
||
type="primary"
|
||
@click="handleCloseQuestion"
|
||
>
|
||
{{ $t('common:button:save') }}
|
||
</el-button>
|
||
</div>
|
||
</el-dialog>
|
||
<!-- 预览单个图像 -->
|
||
<el-dialog
|
||
v-if="imgObj.visible"
|
||
:visible.sync="imgObj.visible"
|
||
:title="$t('trials:uploadNonDicoms:dialogTitle:preview')"
|
||
append-to-body
|
||
width="565px"
|
||
>
|
||
<div
|
||
v-loading="imgObj.loading"
|
||
class="base-modal-body"
|
||
style="border: 2px solid #ccc; padding: 10px"
|
||
>
|
||
<el-image
|
||
:src="`${OSSclientConfig.basePath}${imgObj.url}`"
|
||
crossorigin="anonymous"
|
||
fit="fit"
|
||
style="height: 500px; width: 500px"
|
||
@error="imgObj.loading = false"
|
||
@load="imgObj.loading = false"
|
||
/>
|
||
</div>
|
||
</el-dialog>
|
||
</div>
|
||
<div class="function-wrapper">
|
||
<!-- 保存 -->
|
||
<el-button
|
||
:disabled="isAudit"
|
||
size="small"
|
||
type="primary"
|
||
round
|
||
@click="handleSave"
|
||
>
|
||
{{ $t('trials:audit:button:save') }}
|
||
</el-button>
|
||
<!-- 发质疑 -->
|
||
<el-button
|
||
:disabled="isAudit"
|
||
size="small"
|
||
type="primary"
|
||
round
|
||
@click="handleQC"
|
||
>
|
||
{{ $t('trials:audit:button:question') }}
|
||
</el-button>
|
||
<!-- 历史质疑 -->
|
||
<el-button size="small" type="primary" round @click="handleHistoryQC">
|
||
{{
|
||
`${$t('trials:audit:button:historicalQuestions')}(${
|
||
relationInfo.TotalChallengeCount !== undefined
|
||
? relationInfo.TotalChallengeCount
|
||
: 0
|
||
}, ${
|
||
relationInfo.NotClosedChallengeCount !== undefined
|
||
? relationInfo.NotClosedChallengeCount
|
||
: 0
|
||
})`
|
||
}}
|
||
</el-button>
|
||
|
||
<!-- 审核通过 -->
|
||
<el-button
|
||
:disabled="isAudit"
|
||
size="small"
|
||
type="primary"
|
||
round
|
||
@click="handleQCState(8)"
|
||
>
|
||
{{ $t('trials:audit:button:auditPassed') }}
|
||
</el-button>
|
||
<!-- 审核终止 -->
|
||
<!-- <el-button :disabled="isAudit" size="small" type="primary" round @click="handleQCState(7)">-->
|
||
<!-- {{ $t('trials:audit:button:auditFailed') }}-->
|
||
<!-- </el-button>-->
|
||
</div>
|
||
<!--pet-ct临床数据预览-->
|
||
<el-dialog
|
||
v-if="petVisible"
|
||
:show-close="true"
|
||
:visible.sync="petVisible"
|
||
append-to-body
|
||
>
|
||
<uploadPetClinicalData
|
||
:subject-visit-id="data.Id"
|
||
:data="data"
|
||
:studyData="rowData"
|
||
:allow-add-or-edit="false"
|
||
/>
|
||
</el-dialog>
|
||
</div>
|
||
</template>
|
||
<script>
|
||
import {
|
||
collectNextIQCQuality,
|
||
getNextIQCQuality,
|
||
getVisitQCInfo,
|
||
getQCQuestionAnswerList,
|
||
getHistoryChallengeList,
|
||
getVisitQCStudyAndSeriesList,
|
||
getNoneDicomStudyList,
|
||
verifyCanQCPassedOrFailed,
|
||
verifyQCCanAddChallenge,
|
||
setSeriesStatus,
|
||
addOrUpdateNoneDicomStudy,
|
||
addOrUpdateQCQuestionAnswerList,
|
||
addOrUpdateQCChallenge,
|
||
closeQCChallenge,
|
||
updateModality,
|
||
getQCChallengeDialogList,
|
||
} from '@/api/trials'
|
||
import { qCPassedOrFailed } from '@/api/trials/visit'
|
||
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
|
||
import ChatForm from './chatForm'
|
||
import QuestionForm from './questions'
|
||
import moment from 'moment'
|
||
import ClinicalData from './clinicalData'
|
||
import SignForm from '@/views/trials/components/newSignForm'
|
||
import { getToken } from '@/utils/auth'
|
||
import const_ from '@/const/sign-code'
|
||
import uploadPetClinicalData from '@/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue'
|
||
import { downLoadFile } from '@/utils/stream.js'
|
||
import { getCRCUploadedStudyInfo, downloadImageSuccess } from '@/api/load.js'
|
||
import store from '@/store'
|
||
export default {
|
||
name: 'QualityAssurance',
|
||
components: {
|
||
ChatForm,
|
||
ClinicalData,
|
||
QuestionForm,
|
||
SignForm,
|
||
uploadPetClinicalData,
|
||
},
|
||
props: {
|
||
data: {
|
||
type: Object,
|
||
default() {
|
||
return {}
|
||
},
|
||
},
|
||
disabled: {
|
||
type: Boolean,
|
||
default: false,
|
||
},
|
||
qType: {
|
||
type: Number,
|
||
default: 1,
|
||
},
|
||
},
|
||
computed: {
|
||
isEN() {
|
||
return this.$i18n.locale !== 'zh'
|
||
},
|
||
},
|
||
data() {
|
||
return {
|
||
activeName: this.data.DicomStudyCount > 0 ? 'dicom' : 'none-dicom',
|
||
questionForm: {},
|
||
qCQuestionAnswerList: [],
|
||
studyList: [],
|
||
seriesList: [],
|
||
relationInfo: {},
|
||
noneDicomStudyList: [],
|
||
qcForm: {
|
||
subjectVisitId: '',
|
||
challengeType: '',
|
||
content: '',
|
||
actionContent: '',
|
||
deadlineTime: '',
|
||
qcContent: '',
|
||
},
|
||
qcVisible: false,
|
||
chatVisible: false,
|
||
loading: false,
|
||
btnLoading: false,
|
||
historyVisible: false,
|
||
historyList: [],
|
||
historyLoading: false,
|
||
editStudyInfoVisible: false,
|
||
studyForm: {
|
||
StudyCode: '',
|
||
IsDicomData: true,
|
||
Modalities: '',
|
||
BodyPartForEdit: [],
|
||
SeriesCount: null,
|
||
StudyTime: '',
|
||
},
|
||
currentQCRow: {},
|
||
isAudit: false, // 审核过之后功能按钮禁用标识
|
||
qcType: '',
|
||
trialBodyPartTypes: [],
|
||
trialModalitys: [],
|
||
signVisible: false,
|
||
signCode: '',
|
||
auditState: null,
|
||
currentNoneDicomId: '',
|
||
editNoneDicomVisible: false,
|
||
noneDicomForm: {
|
||
Id: '',
|
||
CodeView: '',
|
||
BodyParts: [],
|
||
Modality: '',
|
||
ImageDate: '',
|
||
StudyName: '',
|
||
},
|
||
subjectClinicalData: {},
|
||
moment,
|
||
currentQCType: null,
|
||
currentUser: zzSessionStorage.getItem('userName'),
|
||
pickerOption: {
|
||
disabledDate: (time) => {
|
||
return time.getTime() > Date.now()
|
||
},
|
||
},
|
||
isHaveFirstGiveMedicineDate: false,
|
||
baseDate: '',
|
||
upperLimit: '', // 超期上限
|
||
lowerLimit: '', // 超期下限
|
||
closeQuestionForm: {
|
||
Id: '',
|
||
SubjectVisitId: '',
|
||
Type: null,
|
||
Reason: '',
|
||
Remake: '',
|
||
},
|
||
closeBtnLoading: false,
|
||
closeQuestionVisible: false,
|
||
trialId: '',
|
||
dictionaryList: {},
|
||
currentSeriesIsReading: false,
|
||
currentSeriesIsDeleted: false,
|
||
imgObj: { url: '', visible: false, loading: false },
|
||
open: null,
|
||
existsManual: false,
|
||
|
||
// pet-ct临床数据
|
||
petVisible: false,
|
||
rowData: {},
|
||
IsHaveStudyClinicalData: false,
|
||
BodyPart: {},
|
||
|
||
// 下载相关
|
||
downloading: false,
|
||
selectTableDicom: [], // 选中的dicom数据
|
||
selectTableNonedicom: [], // 选中的非dicom数据
|
||
downloadId: null,
|
||
}
|
||
},
|
||
async mounted() {
|
||
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
|
||
if (this.disabled) {
|
||
this.isAudit = true
|
||
this.currentQCType = this.qType
|
||
} else {
|
||
this.currentQCType = this.data.AuditState < 6 ? 1 : 2
|
||
}
|
||
window.addEventListener('message', this.receiveMsg)
|
||
|
||
this.trialId = this.$route.query.trialId
|
||
this.getQCInfo()
|
||
this.getDicData()
|
||
// this.handleViewImages()
|
||
// this.handleViewAllNoneDicoms()
|
||
},
|
||
beforeDestroy() {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
store.dispatch('trials/setUnLock', false)
|
||
},
|
||
methods: {
|
||
// 选中dicom
|
||
handleSelectionChangeDicom(val) {
|
||
this.selectTableDicom = val
|
||
},
|
||
// 选中非dicom
|
||
handleSelectionChangeNonedicom(val) {
|
||
this.selectTableNonedicom = val
|
||
},
|
||
// 获取下载文件信息
|
||
async getCRCUploadedStudyInfo(type) {
|
||
if (this.downloading) return
|
||
try {
|
||
let data = {
|
||
SubjectVisitId: this.data.Id,
|
||
NoneDicomStudyIdList: [],
|
||
DicomStudyIdList: [],
|
||
}
|
||
if (type === 'dicom') {
|
||
data.DicomStudyIdList = this.selectTableDicom.map(
|
||
(item) => item.StudyId
|
||
)
|
||
}
|
||
if (type === 'noneDicom') {
|
||
console.log(this.selectTableNonedicom)
|
||
data.NoneDicomStudyIdList = this.selectTableNonedicom.map(
|
||
(item) => item.Id
|
||
)
|
||
}
|
||
this.downloading = true
|
||
let res = await getCRCUploadedStudyInfo(data)
|
||
this.downloading = false
|
||
if (res.IsSuccess) {
|
||
this.downloadId = res.OtherInfo
|
||
this.downloadImage(res.Result, type)
|
||
}
|
||
} catch (err) {
|
||
this.downloading = false
|
||
console.log(err)
|
||
}
|
||
},
|
||
// 打包下载
|
||
async downloadImage(data, type) {
|
||
try {
|
||
let { files, name, fileType } = this.formatDownloadFile(data, type)
|
||
let res = null
|
||
if (fileType === 'list') {
|
||
res = await downLoadFile(files, name, 'zip')
|
||
} else {
|
||
res = await downLoadFile(files, name)
|
||
}
|
||
if (res && this.downloadId) {
|
||
this.downloadImageSuccess()
|
||
}
|
||
} catch (err) {
|
||
console.log(err)
|
||
}
|
||
},
|
||
// 格式化下载文件路径
|
||
formatDownloadFile(data, type) {
|
||
let files = [],
|
||
name = null
|
||
if (type === 'dicom') {
|
||
name = `${data.SubjectCode}_${data.VisitName}_${this.$fd(
|
||
'IsDicom',
|
||
true
|
||
)}.zip`
|
||
let StudyList = data.StudyList
|
||
StudyList.forEach((study) => {
|
||
if (study.SeriesList.length > 0) {
|
||
study.SeriesList.forEach((series) => {
|
||
if (series.InstanceList.length > 0) {
|
||
series.InstanceList.forEach((instance) => {
|
||
let fileName = instance.Path.split('/').pop()
|
||
let obj = {
|
||
name: `${data.SubjectCode}_${data.VisitName}_${this.$fd(
|
||
'IsDicom',
|
||
true
|
||
)}/${study.StudyCode}_${study.StudyTime.split(' ')[0]}_${
|
||
series.Modality
|
||
}/${fileName}`,
|
||
url: this.OSSclientConfig.basePath + instance.Path,
|
||
}
|
||
files.push(obj)
|
||
})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
}
|
||
if (type === 'noneDicom') {
|
||
name = `${data.SubjectCode}_${data.VisitName}_${this.$fd(
|
||
'IsDicom',
|
||
false
|
||
)}.zip`
|
||
let NoneDicomStudyList = data.NoneDicomStudyList
|
||
// 单个zip包
|
||
if (
|
||
NoneDicomStudyList.length === 1 &&
|
||
NoneDicomStudyList[0].FileList.length === 1 &&
|
||
NoneDicomStudyList[0].FileList[0].FileType.includes('zip')
|
||
) {
|
||
files =
|
||
this.OSSclientConfig.basePath +
|
||
NoneDicomStudyList[0].FileList[0].Path
|
||
return { files, name, fileType: 'one' }
|
||
}
|
||
// 多文件
|
||
NoneDicomStudyList.forEach((study) => {
|
||
if (study.FileList.length > 0) {
|
||
study.FileList.forEach((item) => {
|
||
let obj = {
|
||
name: `${data.SubjectCode}_${data.VisitName}_${this.$fd(
|
||
'IsDicom',
|
||
true
|
||
)}/${study.StudyCode}_${study.ImageDate.split(' ')[0]}_${
|
||
study.Modality
|
||
}/${item.FileName}`,
|
||
url: this.OSSclientConfig.basePath + item.Path,
|
||
}
|
||
files.push(obj)
|
||
})
|
||
}
|
||
})
|
||
}
|
||
return { files, name, fileType: 'list' }
|
||
},
|
||
// 影像下载成功确认
|
||
async downloadImageSuccess() {
|
||
try {
|
||
let params = {
|
||
TrialImageDownloadId: this.downloadId,
|
||
}
|
||
await downloadImageSuccess(params)
|
||
} catch (err) {
|
||
console.log(err)
|
||
}
|
||
},
|
||
// 获取QC界面基本信息
|
||
getQCInfo() {
|
||
this.loading = true
|
||
getVisitQCInfo(this.data.Id, this.data.QCProcessEnum, this.currentQCType)
|
||
.then((res) => {
|
||
this.existsManual = res.Result.ExistsManual
|
||
this.qCQuestionAnswerList = res.Result.QCQuestionAnswerList
|
||
this.IsHaveStudyClinicalData = res.Result.IsHaveStudyClinicalData
|
||
this.studyList = res.Result.StudyList
|
||
this.seriesList = res.Result.SeriesList
|
||
this.noneDicomStudyList = res.Result.NoneDicomStudyList
|
||
this.relationInfo = res.Result.RelationInfo
|
||
this.trialBodyPartTypes = this.relationInfo.TrialBodyPartTypes
|
||
? this.relationInfo.TrialBodyPartTypes.trim().split('|')
|
||
: []
|
||
this.trialModalitys = this.relationInfo.TrialModalitys
|
||
? this.relationInfo.TrialModalitys.trim().split('|')
|
||
: []
|
||
this.subjectClinicalData = res.Result.SubjectClinicalData
|
||
this.baseDate = res.Result.RelationInfo.SubjectFirstGiveMedicineTime
|
||
if (this.baseDate) {
|
||
const uDay =
|
||
res.Result.RelationInfo.VisitDay * 1 +
|
||
res.Result.RelationInfo.VisitWindowLeft * 1
|
||
this.upperLimit = moment(this.baseDate, 'YYYY-MM-DD')
|
||
.add(uDay, 'days')
|
||
.format('YYYY-MM-DD')
|
||
const lDay =
|
||
res.Result.RelationInfo.VisitDay * 1 +
|
||
res.Result.RelationInfo.VisitWindowRight * 1
|
||
this.lowerLimit = moment(this.baseDate, 'YYYY-MM-DD')
|
||
.add(lDay, 'days')
|
||
.format('YYYY-MM-DD')
|
||
}
|
||
this.isHaveFirstGiveMedicineDate =
|
||
res.Result.RelationInfo.IsHaveFirstGiveMedicineDate
|
||
this.loading = false
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
// 刷新审核问题列表
|
||
getCheckList() {
|
||
this.loading = true
|
||
getQCQuestionAnswerList(
|
||
this.trialId,
|
||
this.data.Id,
|
||
this.data.QCProcessEnum,
|
||
this.currentQCType
|
||
)
|
||
.then((res) => {
|
||
this.loading = false
|
||
res.Result.forEach((element, index) => {
|
||
// this.qCQuestionAnswerList
|
||
this.$set(this.qCQuestionAnswerList[index], 'Id', element.Id)
|
||
})
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
// 保存审核问题
|
||
handleSave(isMessage) {
|
||
return new Promise((resolve) => {
|
||
this.$refs['questions']
|
||
.submit()
|
||
.then((res) => {
|
||
var answerList = []
|
||
res.forEach((item) => {
|
||
var index = this.qCQuestionAnswerList.findIndex(
|
||
(v) => v.TrialQCQuestionConfigureId === item.Id
|
||
)
|
||
if (index > -1) {
|
||
answerList.push({
|
||
id: this.qCQuestionAnswerList[index].Id,
|
||
answer: item.answer,
|
||
trialQCQuestionConfigureId: item.Id,
|
||
})
|
||
}
|
||
})
|
||
this.loading = true
|
||
addOrUpdateQCQuestionAnswerList(
|
||
this.trialId,
|
||
this.data.Id,
|
||
this.data.QCProcessEnum,
|
||
this.currentQCType,
|
||
answerList
|
||
)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
if (isMessage !== true) {
|
||
this.$message.success(
|
||
this.$t('common:message:savedSuccessfully')
|
||
)
|
||
}
|
||
this.getCheckList()
|
||
resolve(true)
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
resolve(false)
|
||
})
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
resolve(false)
|
||
})
|
||
})
|
||
},
|
||
// 保存质疑
|
||
handleSaveQC() {
|
||
this.$refs['qcForm'].validate((valid) => {
|
||
if (!valid) return
|
||
this.btnLoading = true
|
||
this.qcForm.subjectVisitId = this.data.Id
|
||
var contents = []
|
||
var types = []
|
||
var actions = []
|
||
this.qcForm.qcContent.forEach((item) => {
|
||
if (item.isSelect) {
|
||
types.push(`${item.keyName}`)
|
||
var str = `${item.keyName}<br>`
|
||
if (item.keyValue) {
|
||
// 问题总结
|
||
str = `${str}${this.$t(
|
||
'trials:audit:form:questionSummary'
|
||
)}:<br>${item.keyValue}<br>`
|
||
}
|
||
if (item.actionContent) {
|
||
// 行动事项
|
||
actions.push(`${item.actionContent}`)
|
||
str = `${str}${this.$t(
|
||
'trials:audit:form:actionMatters'
|
||
)}:<br><div style='margin-left:20px'>${item.actionContent}</div>`
|
||
}
|
||
contents.push(str)
|
||
}
|
||
})
|
||
if (contents.length === 0) {
|
||
// 质疑内容不能为空!
|
||
this.$alert(this.$t('trials:audit:message:qsContentIsNull'))
|
||
this.btnLoading = false
|
||
return
|
||
} else {
|
||
this.qcForm.content = contents.join('|')
|
||
this.qcForm.challengeType = types.join('|')
|
||
this.qcForm.actionContent = actions.join('|')
|
||
}
|
||
var params = {
|
||
challengeType: this.qcForm.challengeType,
|
||
subjectVisitId: this.qcForm.subjectVisitId,
|
||
content: this.qcForm.content,
|
||
actionContent: this.qcForm.actionContent,
|
||
reuploadEnum: 0,
|
||
deadlineTime: this.qcForm.deadlineTime,
|
||
}
|
||
addOrUpdateQCChallenge(
|
||
this.trialId,
|
||
this.data.QCProcessEnum,
|
||
this.currentQCType,
|
||
params
|
||
)
|
||
.then((res) => {
|
||
this.btnLoading = false
|
||
if (res.IsSuccess) {
|
||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||
this.qcVisible = false
|
||
this.relationInfo.TotalChallengeCount++
|
||
this.relationInfo.NotClosedChallengeCount++
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.btnLoading = false
|
||
})
|
||
})
|
||
},
|
||
// 打开发起质疑弹窗
|
||
handleQC() {
|
||
this.loading = true
|
||
// 检验qc审核问题是否保存,否则不允许发质疑
|
||
verifyQCCanAddChallenge(this.trialId, this.data.Id, this.currentQCType)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
this.renderQCForm()
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
handleQCVerify() {
|
||
this.loading = true
|
||
return new Promise((resolve) => {
|
||
verifyQCCanAddChallenge(this.trialId, this.data.Id, this.currentQCType)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
resolve(true)
|
||
} else {
|
||
resolve(false)
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
resolve(false)
|
||
})
|
||
})
|
||
},
|
||
// 渲染发质疑窗口
|
||
renderQCForm() {
|
||
var contents = []
|
||
const challengeType = this.dictionaryList['ChallengeType']
|
||
challengeType.forEach((i) => {
|
||
contents.push({ keyName: i.Value, keyValue: '', isSelect: false })
|
||
})
|
||
var isHyperwindow = false
|
||
if (this.isHaveFirstGiveMedicineDate && !!this.baseDate) {
|
||
isHyperwindow = this.isHyperwindow()
|
||
}
|
||
if (isHyperwindow) {
|
||
contents.push({
|
||
keyName: this.$t('trials:audit:message:qsOverWindow'),
|
||
keyValue: `${this.$t('trials:audit:message:qsOverWindow1')}:${
|
||
this.upperLimit
|
||
}~${this.lowerLimit},${this.$t(
|
||
'trials:audit:message:qsOverWindow2'
|
||
)}:${moment(this.relationInfo.EarliestScanDate).format(
|
||
'YYYY-MM-DD'
|
||
)}~${moment(this.relationInfo.LatestScanDate).format(
|
||
'YYYY-MM-DD'
|
||
)},${this.$t('trials:audit:message:qsOverWindow3')}`,
|
||
isSelect: false,
|
||
actionContent: this.$t('trials:audit:message:qsOverWindow4'),
|
||
})
|
||
}
|
||
this.qcForm.qcContent = contents
|
||
const day = this.relationInfo.TrialChangeDefalutDays
|
||
this.qcForm.deadlineTime = moment()
|
||
.add(day * 1, 'days')
|
||
.format('YYYY-MM-DD HH:mm:ss')
|
||
this.qcVisible = true
|
||
},
|
||
isHyperwindow() {
|
||
var isHyperwindow = false
|
||
if (
|
||
this.relationInfo.EarliestScanDate < this.upperLimit ||
|
||
this.relationInfo.LatestScanDate > this.lowerLimit
|
||
) {
|
||
isHyperwindow = true
|
||
}
|
||
return isHyperwindow
|
||
},
|
||
// 获取字典数据
|
||
getDicData() {
|
||
getBasicDataSelects(['ChallengeType']).then((res) => {
|
||
this.dictionaryList = { ...res.Result }
|
||
})
|
||
},
|
||
// 打开历史质疑弹窗
|
||
handleHistoryQC() {
|
||
this.historyVisible = true
|
||
this.getHistoryInfo()
|
||
},
|
||
// 获取历史质疑记录
|
||
getHistoryInfo() {
|
||
this.historyLoading = true
|
||
getHistoryChallengeList(
|
||
this.data.Id,
|
||
this.data.QCProcessEnum,
|
||
this.currentQCType
|
||
)
|
||
.then((res) => {
|
||
this.historyList = res.Result
|
||
this.historyLoading = false
|
||
})
|
||
.catch(() => {
|
||
this.historyLoading = false
|
||
})
|
||
},
|
||
|
||
// 回复质疑
|
||
handleReply(row) {
|
||
this.historyLoading = true
|
||
getQCChallengeDialogList(row.Id)
|
||
.then((res) => {
|
||
this.historyLoading = false
|
||
if (res.IsSuccess) {
|
||
if (res.Result.length > 0) {
|
||
Object.assign(row, res.Result[0])
|
||
}
|
||
this.currentQCRow = { ...row }
|
||
this.chatVisible = true
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.historyLoading = false
|
||
})
|
||
},
|
||
getDialogList() {
|
||
this.historyLoading = true
|
||
getQCChallengeDialogList(this.currentQCRow.Id)
|
||
.then((res) => {
|
||
this.historyLoading = false
|
||
if (res.IsSuccess && res.Result.length > 0) {
|
||
var i = this.historyList.findIndex(
|
||
(item) => item.Id === this.currentQCRow.Id
|
||
)
|
||
if (i > -1) {
|
||
this.currentQCRow = Object.assign(
|
||
this.historyList[i],
|
||
res.Result[0]
|
||
)
|
||
}
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.historyLoading = false
|
||
})
|
||
},
|
||
// 关闭质疑
|
||
handleCloseQuestion() {
|
||
this.$refs['closeQuestionForm'].validate((valid) => {
|
||
if (!valid) return
|
||
this.closeBtnLoading = true
|
||
if (this.closeQuestionForm.Type === 1) {
|
||
// 问题已解决
|
||
this.closeQuestionForm.Reason = this.$t(
|
||
'trials:qcQuality:message:problemSolved'
|
||
)
|
||
} else if (this.closeQuestionForm.Type === 2) {
|
||
// 问题无法解决强制关闭质疑,已提醒中心下次注意
|
||
this.closeQuestionForm.Reason = `${this.$t(
|
||
'trials:qcQuality:message:problemNotSolved'
|
||
)}<br/><br/>${this.$t('trials:consistencyCheck:label:closereason')}:${
|
||
this.closeQuestionForm.Remake
|
||
}`
|
||
}
|
||
var params = {
|
||
TrialId: this.data.TrialId,
|
||
QcChallengeId: this.closeQuestionForm.Id,
|
||
SubjectVisitId: this.data.Id,
|
||
CloseEnum: this.closeQuestionForm.Type,
|
||
CloseReason: this.closeQuestionForm.Reason,
|
||
}
|
||
closeQCChallenge(params)
|
||
.then((res) => {
|
||
this.closeBtnLoading = false
|
||
if (res.IsSuccess) {
|
||
this.getHistoryInfo()
|
||
this.$message.success(
|
||
this.$t('trials:qcQuality:message:closedSuccessfully')
|
||
)
|
||
this.closeQuestionVisible = false
|
||
this.relationInfo.NotClosedChallengeCount--
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.closeBtnLoading = false
|
||
})
|
||
})
|
||
},
|
||
// 打开关闭质疑框并初始化
|
||
handleCloseQC(row) {
|
||
this.closeQuestionForm = Object.assign(this.closeQuestionForm, row)
|
||
this.closeQuestionForm.CurrentQCType = this.currentQCType
|
||
this.closeQuestionForm.AuditState = this.data.AuditState
|
||
this.closeQuestionForm.TrialQCProcess = this.data.QCProcessEnum
|
||
this.closeQuestionForm.Type = null
|
||
this.closeQuestionForm.Reason = ''
|
||
this.closeQuestionForm.Remake = ''
|
||
this.closeQuestionVisible = true
|
||
},
|
||
// 打开质疑记录弹窗
|
||
handleQCInfo(row) {
|
||
this.currentQCRow = { ...row }
|
||
this.chatVisible = true
|
||
},
|
||
changeReadingStatus(callback, row) {
|
||
let statusStr = ''
|
||
if (callback) {
|
||
statusStr = this.$t('trials:audit:label:setSeriesReading')
|
||
row.IsReading = false
|
||
} else {
|
||
statusStr = this.$t('trials:audit:label:setSeriesNotReading')
|
||
row.IsReading = true
|
||
}
|
||
var message = this.$t('trials:audit:message:changeSeriesStatus').replace(
|
||
'xxx',
|
||
statusStr
|
||
)
|
||
message = message.replace('yyy', this.$fd('YesOrNo', !row.IsReading))
|
||
this.$confirm(message, {
|
||
distinguishCancelAndClose: true,
|
||
type: 'warning',
|
||
})
|
||
.then(() => {
|
||
const state = row.IsReading ? 1 : 2
|
||
this.loading = true
|
||
setSeriesStatus(
|
||
this.trialId,
|
||
this.data.Id,
|
||
row.StudyId,
|
||
row.Id,
|
||
state
|
||
)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
this.$message.success(
|
||
this.$t('common:message:savedSuccessfully')
|
||
)
|
||
this.getStudyInfo()
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
})
|
||
.catch(() => {})
|
||
},
|
||
changeDeleteStatus(callback, row) {
|
||
let statusStr = ''
|
||
if (callback) {
|
||
statusStr = this.$t('trials:audit:label:setSeriesDeleted')
|
||
row.IsDeleted = false
|
||
} else {
|
||
statusStr = this.$t('trials:audit:label:setSeriesNotDelete')
|
||
row.IsDeleted = true
|
||
}
|
||
var message = this.$t('trials:audit:message:changeSeriesStatus').replace(
|
||
'xxx',
|
||
statusStr
|
||
)
|
||
message = message.replace('yyy', this.$fd('YesOrNo', !row.IsDeleted))
|
||
this.$confirm(message, {
|
||
distinguishCancelAndClose: true,
|
||
type: 'warning',
|
||
})
|
||
.then(() => {
|
||
const state = row.IsDeleted ? 5 : 4
|
||
this.loading = true
|
||
setSeriesStatus(
|
||
this.trialId,
|
||
this.data.Id,
|
||
row.StudyId,
|
||
row.Id,
|
||
state
|
||
)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
this.$message.success(
|
||
this.$t('common:message:savedSuccessfully')
|
||
)
|
||
this.getStudyInfo()
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
})
|
||
.catch(() => {})
|
||
},
|
||
receiveMsg(event) {
|
||
if (event.data.type === 'refreshSeriesList') {
|
||
this.getStudyInfo()
|
||
}
|
||
},
|
||
// 刷新检查新
|
||
getStudyInfo() {
|
||
this.loading = true
|
||
getVisitQCStudyAndSeriesList(this.data.Id)
|
||
.then((res) => {
|
||
this.loading = false
|
||
this.studyList = res.Result.StudyList
|
||
this.seriesList = res.Result.SeriesList
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
// 设置qc通过/不通过
|
||
async handleQCState(auditState) {
|
||
if (auditState === 7) {
|
||
this.signCode = this.getSignCode(auditState)
|
||
this.signVisible = true
|
||
this.auditState = auditState
|
||
return
|
||
}
|
||
if (auditState === 8) {
|
||
var isgo = true
|
||
var hasStudyName = true,
|
||
hasStudyNameList = []
|
||
var isgoList = []
|
||
this.studyList.forEach((v) => {
|
||
if (!v.BodyPartForEdit) {
|
||
isgo = false
|
||
isgoList.push(v.StudyCode)
|
||
}
|
||
if (this.relationInfo.IsShowStudyName && !v.StudyName) {
|
||
hasStudyName = false
|
||
hasStudyNameList.push(v.StudyCode)
|
||
}
|
||
})
|
||
if (!hasStudyName) {
|
||
// `请补充检查${isgoList.toString()}的检查名称!`
|
||
this.$confirm(
|
||
this.$t('trials:qcQuality:title:noStudyName').replace(
|
||
'xxx',
|
||
hasStudyNameList.join('、 ')
|
||
),
|
||
'',
|
||
{
|
||
showCancelButton: false,
|
||
}
|
||
)
|
||
return
|
||
}
|
||
if (!isgo) {
|
||
// `请补充检查${isgoList.toString()}的检查部位!`
|
||
this.$confirm(
|
||
this.$t('trials:qcQuality:title:title1').replace(
|
||
'xxx',
|
||
isgoList.join('、 ')
|
||
),
|
||
'',
|
||
{
|
||
showCancelButton: false,
|
||
}
|
||
)
|
||
return
|
||
}
|
||
}
|
||
this.loading = true
|
||
var isVerify = await this.handleSave(true)
|
||
if (!isVerify) {
|
||
return
|
||
}
|
||
// 验证是否关闭所有质疑
|
||
verifyCanQCPassedOrFailed(this.trialId, this.data.Id)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
this.signCode = this.getSignCode(auditState)
|
||
this.signVisible = true
|
||
this.auditState = auditState
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
getSignCode(auditState) {
|
||
if (this.relationInfo.TrialQCProcessEnum === 1 && auditState === 8) {
|
||
// 单审通过
|
||
const { QCSingleReviewPassed } = const_.processSignature
|
||
return QCSingleReviewPassed
|
||
} else if (
|
||
this.relationInfo.TrialQCProcessEnum === 1 &&
|
||
auditState === 7
|
||
) {
|
||
// 单审不通过
|
||
const { QCSingleReviewFailed } = const_.processSignature
|
||
return QCSingleReviewFailed
|
||
} else if (
|
||
this.relationInfo.TrialQCProcessEnum === 2 &&
|
||
auditState === 8 &&
|
||
this.currentQCType === 1
|
||
) {
|
||
// 初审通过
|
||
const { PreliminaryReviewOfQCPassed } = const_.processSignature
|
||
return PreliminaryReviewOfQCPassed
|
||
} else if (
|
||
this.relationInfo.TrialQCProcessEnum === 2 &&
|
||
auditState === 7 &&
|
||
this.currentQCType === 1
|
||
) {
|
||
// 初审不通过
|
||
const { PreliminaryReviewOfQCFailed } = const_.processSignature
|
||
return PreliminaryReviewOfQCFailed
|
||
} else if (
|
||
this.relationInfo.TrialQCProcessEnum === 2 &&
|
||
auditState === 8 &&
|
||
this.currentQCType === 2
|
||
) {
|
||
// 复审通过
|
||
const { SecondaryReviewOfQCPassed } = const_.processSignature
|
||
return SecondaryReviewOfQCPassed
|
||
} else if (
|
||
this.relationInfo.TrialQCProcessEnum === 2 &&
|
||
auditState === 7 &&
|
||
this.currentQCType === 2
|
||
) {
|
||
// 复审不通过
|
||
const { SecondaryReviewOfQCFailed } = const_.processSignature
|
||
return SecondaryReviewOfQCFailed
|
||
}
|
||
},
|
||
// 关闭签名框
|
||
closeSignDialog(isSign, signInfo) {
|
||
if (isSign) {
|
||
this.setQCStatus(signInfo)
|
||
} else {
|
||
this.signVisible = false
|
||
}
|
||
},
|
||
// 设置qc审核状态
|
||
async setQCStatus(signInfo) {
|
||
this.loading = true
|
||
var params = {
|
||
data: {
|
||
TrialId: this.trialId,
|
||
SubjectVisitId: this.data.Id,
|
||
AuditState: this.auditState,
|
||
},
|
||
signInfo: signInfo,
|
||
}
|
||
qCPassedOrFailed(params)
|
||
.then((res) => {
|
||
this.loading = false
|
||
if (res.IsSuccess) {
|
||
this.$refs['signForm'].btnLoading = false
|
||
this.signVisible = false
|
||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||
// this.getQCInfo()
|
||
this.isAudit = true
|
||
this.$forceUpdate()
|
||
getNextIQCQuality({
|
||
trialId: this.trialId,
|
||
SubjectId: this.data.SubjectId,
|
||
}).then((res) => {
|
||
if (res.Result && res.Result.VisitId) {
|
||
this.$confirm(
|
||
this.$t('trials:qcQuality:title:title2', '', {
|
||
showCancelButton: false,
|
||
})
|
||
)
|
||
.then(() => {
|
||
collectNextIQCQuality({
|
||
trialId: this.trialId,
|
||
SubjectId: this.data.SubjectId,
|
||
}).then((res) => {
|
||
this.$emit('getList')
|
||
this.$emit('nextTask', res.Result.VisitId)
|
||
})
|
||
})
|
||
.catch(() => {
|
||
this.$emit('getList')
|
||
})
|
||
} else {
|
||
// 没有后续质控任务
|
||
this.$emit('getList')
|
||
this.$confirm(this.$t('trials:qcQuality:title:closeQCDialog'))
|
||
.then(() => {
|
||
this.$emit('close')
|
||
})
|
||
.catch(() => {})
|
||
}
|
||
})
|
||
}
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
this.$refs['signForm'].btnLoading = false
|
||
})
|
||
},
|
||
getNextQCInfo() {
|
||
// '是否确认进入下一个质控任务?'
|
||
var message = this.$t('trials:qcQuality:title:title2')
|
||
|
||
this.$confirm(message, {
|
||
type: 'warning',
|
||
distinguishCancelAndClose: true,
|
||
})
|
||
.then(() => {
|
||
this.loading = true
|
||
this.$emit('nextTask')
|
||
})
|
||
.catch((action) => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
// 设置已删除序列行样式
|
||
tableRowClassName({ row, rowIndex }) {
|
||
if (row.IsDeleted) {
|
||
return 'delete-row'
|
||
} else {
|
||
return ''
|
||
}
|
||
},
|
||
// 打开检查信息编辑框
|
||
handleEditStudy(row) {
|
||
this.editStudyInfoVisible = true
|
||
this.studyForm = { ...row }
|
||
var bodyPart = []
|
||
if (this.studyForm.BodyPartForEdit.indexOf('|') !== -1) {
|
||
bodyPart = this.studyForm.BodyPartForEdit.split('|')
|
||
} else if (this.studyForm.BodyPartForEdit !== '') {
|
||
bodyPart.push(this.studyForm.BodyPartForEdit)
|
||
}
|
||
this.$set(this.studyForm, 'Modality', row.ModalityForEdit)
|
||
// this.studyForm.Modality = row.ModalityForEdit
|
||
this.studyForm.BodyPartForEdit = bodyPart
|
||
},
|
||
// 更新拍片部位/拍片类型信息
|
||
handleUpdateStudyInfo() {
|
||
this.$refs['studyForm'].validate((valid) => {
|
||
if (!valid) return
|
||
this.btnLoading = true
|
||
this.studyForm.BodyPart = this.studyForm.BodyPartForEdit.join('|')
|
||
// this.studyForm.Modality = this.studyForm.Modalities
|
||
var params = {
|
||
id: this.studyForm.StudyId,
|
||
subjectVisitId: this.data.Id,
|
||
type: 1,
|
||
modality: this.studyForm.Modality,
|
||
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
|
||
})
|
||
})
|
||
},
|
||
// 设置重传时刷新历史质疑列表及影响指控列表
|
||
refreshList() {
|
||
// 如果是复审时候设置重传,需要将当前审核状态设置为初审,且刷新页面数据并关闭历史质疑和质疑记录窗口
|
||
if (this.currentQCType === 2) {
|
||
this.currentQCType = 1
|
||
// this.getQCInfo()
|
||
this.getHistoryInfo()
|
||
} else {
|
||
// 如果是初审时候设置重传,不影响
|
||
this.getHistoryInfo()
|
||
}
|
||
this.$emit('getList')
|
||
},
|
||
|
||
// 打开非Dicom信息编辑框
|
||
handleEditNoneDicomInfo(row) {
|
||
const { CodeView, Id, BodyPart, Modality, ImageDate, StudyName } = {
|
||
...row,
|
||
}
|
||
this.noneDicomForm.StudyName = StudyName
|
||
this.noneDicomForm.CodeView = CodeView
|
||
this.noneDicomForm.Id = Id
|
||
this.noneDicomForm.BodyPart = BodyPart
|
||
this.noneDicomForm.Modality = Modality
|
||
this.noneDicomForm.ImageDate = ImageDate
|
||
this.noneDicomForm.BodyParts = BodyPart.split(', ')
|
||
this.editNoneDicomVisible = true
|
||
},
|
||
// 更新非Dicom部位/拍片类型信息
|
||
handleUpdateNoneDicomInfo() {
|
||
this.$refs.noneDicomForm.validate((valid) => {
|
||
if (!valid) return
|
||
this.btnLoading = true
|
||
this.noneDicomForm.BodyPart = this.noneDicomForm.BodyParts.join(', ')
|
||
this.noneDicomForm.TrialId = this.trialId
|
||
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
|
||
})
|
||
})
|
||
},
|
||
// 获取非Dicom检查信息
|
||
getNoneDicomList() {
|
||
this.loading = true
|
||
getNoneDicomStudyList(this.data.Id)
|
||
.then((res) => {
|
||
this.noneDicomStudyList = res.Result
|
||
this.loading = false
|
||
})
|
||
.catch(() => {
|
||
this.loading = false
|
||
})
|
||
},
|
||
// 预览文件
|
||
previewFile(row) {
|
||
if (!!~row.FileType.indexOf('pdf')) {
|
||
return this.$preview({
|
||
path: row.Path || row.fullPath,
|
||
type: 'pdf',
|
||
title: row.FileName,
|
||
})
|
||
}
|
||
// window.open(row.FullFilePath, '_blank')
|
||
// this.imgObj.url = row.FullFilePath
|
||
// this.imgObj.loading = true
|
||
// this.imgObj.visible = true
|
||
this.$refs[row.FullFilePath].$viewer.show()
|
||
},
|
||
// 预览所有影像
|
||
handleViewImages() {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
var token = getToken()
|
||
const routeData = this.$router.resolve({
|
||
path: `/showvisitdicoms?trialId=${this.data.TrialId}&visitInfo=${
|
||
this.data.VisitName
|
||
}(${this.data.VisitNum})&subjectVisitId=${this.data.Id}&showDelete=${
|
||
this.isAudit ? 0 : 1
|
||
}&TokenKey=${token}`,
|
||
})
|
||
this.open = window.open(routeData.href, '_blank')
|
||
},
|
||
// 预览阅片影像
|
||
handleViewReadingImages() {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
var token = getToken()
|
||
const routeData = this.$router.resolve({
|
||
path: `/showvisitdicoms?trialId=${this.data.TrialId}&visitInfo=${this.data.VisitName}(${this.data.VisitNum})&subjectVisitId=${this.data.Id}&isReading=1&TokenKey=${token}`,
|
||
})
|
||
this.open = window.open(routeData.href, '_blank')
|
||
},
|
||
// 预览临床数据
|
||
handlePreviewClinicalData(row) {
|
||
this.rowData = row
|
||
this.petVisible = true
|
||
},
|
||
// 预览某个检查
|
||
handlePreviewStudy(row) {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
var token = getToken()
|
||
const routeData = this.$router.resolve({
|
||
path: `/showdicom?trialId=${this.trialId}&subjectVisitId=${
|
||
this.data.Id
|
||
}&studyId=${row.StudyId}&showDelete=${
|
||
this.isAudit ? 0 : 1
|
||
}&TokenKey=${token}&type=Study`,
|
||
})
|
||
this.open = window.open(routeData.href, '_blank')
|
||
},
|
||
// 预览某个序列
|
||
handlePreviewInstance(row) {
|
||
try {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
var token = getToken()
|
||
const routeData = this.$router.resolve({
|
||
path: `/showdicom?trialId=${this.trialId}&studyId=${
|
||
row.StudyId
|
||
}&studyCode=${row.StudyCode}&modality=${row.Modality}&seriesId=${
|
||
row.Id
|
||
}&seriesNumber=${row.SeriesNumber}&showDelete=${
|
||
this.isAudit ? 0 : 1
|
||
}&subjectVisitId=${
|
||
this.data.Id
|
||
}&type=Series&TokenKey=${token}&description=${row.Description}`,
|
||
})
|
||
this.open = window.open(routeData.href, '_blank')
|
||
} catch (e) {
|
||
console.log(e)
|
||
}
|
||
},
|
||
// 预览所有检查下非Dicom文件
|
||
handleViewAllNoneDicoms() {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
// this.previewAllNoneDicomVisible = true
|
||
let trialId = this.$route.query.trialId
|
||
var token = getToken()
|
||
const routeData = this.$router.resolve({
|
||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&TokenKey=${token}`,
|
||
})
|
||
this.open = window.open(routeData.href, '_blank')
|
||
},
|
||
// 预览单个检查下非Dicom文件
|
||
handlePreviewNoneDicomFiles(row) {
|
||
if (this.open) {
|
||
this.open.close()
|
||
}
|
||
let trialId = this.$route.query.trialId
|
||
var token = getToken()
|
||
const routeData = this.$router.resolve({
|
||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&studyId=${row.Id}&TokenKey=${token}`,
|
||
})
|
||
this.open = window.open(routeData.href, '_blank')
|
||
},
|
||
getBodyPart(bodyPart) {
|
||
if (!bodyPart) return ''
|
||
var separator = ','
|
||
if (bodyPart.indexOf('|') > -1) {
|
||
separator = '|'
|
||
} else if (bodyPart.indexOf(',') > -1) {
|
||
separator = ','
|
||
} else if (bodyPart.indexOf(',') > -1) {
|
||
separator = ','
|
||
}
|
||
var arr = bodyPart.split(separator)
|
||
var newArr = arr.map((i) => {
|
||
return this.$fd('Bodypart', i.trim(), 'Code', this.BodyPart, 'Name')
|
||
})
|
||
return newArr.join(' | ')
|
||
},
|
||
openManuals() {
|
||
this.$emit('openManuals')
|
||
},
|
||
},
|
||
}
|
||
</script>
|
||
<style lang="scss" scoped>
|
||
.qa-wrapper {
|
||
display: flex;
|
||
flex-flow: column;
|
||
height: 100%;
|
||
border: 1px solid #fff;
|
||
padding: 10px;
|
||
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
|
||
.function-wrapper {
|
||
text-align: right;
|
||
}
|
||
.qa-content {
|
||
flex: 1;
|
||
margin-top: 10px;
|
||
overflow-y: auto;
|
||
}
|
||
::v-deep .delete-row {
|
||
text-decoration-line: line-through;
|
||
color: #c0c4cc;
|
||
}
|
||
::v-deep .el-card {
|
||
padding: 10px;
|
||
}
|
||
}
|
||
::v-deep .tip-i {
|
||
&::before {
|
||
color: #fff !important;
|
||
}
|
||
}
|
||
</style>
|