1248 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			Plaintext
		
	
	
			
		
		
	
	
			1248 lines
		
	
	
		
			45 KiB
		
	
	
	
		
			Plaintext
		
	
	
| <template>
 | ||
|   <div class="upload-dicom-files-wrapper">
 | ||
|     <!-- 已上传的dicom影像记录 -->
 | ||
|     <div class="functions" style="text-align:right">
 | ||
|       <!-- //批量删除已上传的影像 -->
 | ||
|       <el-button
 | ||
|         :disabled="deleteArr.length === 0"
 | ||
|         type="primary"
 | ||
|         size="small"
 | ||
|         icon="el-icon-delete"
 | ||
|         @click="handleBatchDelete"
 | ||
|       >
 | ||
|         {{ $t('trials:uploadedDicoms:action:delete') }}
 | ||
|       </el-button>
 | ||
|       <!-- 预览 -->
 | ||
|       <el-button
 | ||
|         type="primary"
 | ||
|         icon="el-icon-view"
 | ||
|         size="small"
 | ||
|         :disabled="studyList.length === 0"
 | ||
|         @click="handlePreviewAllFiles"
 | ||
|       >
 | ||
|         {{ $t('trials:uploadedDicoms:action:preview') }}
 | ||
|       </el-button>
 | ||
|     </div>
 | ||
|     <el-table
 | ||
|       v-loading="studyLoading"
 | ||
|       :data="studyList"
 | ||
|       style="width: 100%"
 | ||
|       :row-class-name="tableRowClassName"
 | ||
|       max-height="250"
 | ||
|       @selection-change="handleUploadedSelectionChange"
 | ||
|     >
 | ||
|       <el-table-column
 | ||
|         type="selection"
 | ||
|         width="55"
 | ||
|       />
 | ||
|       <!-- 检查编号 -->
 | ||
|       <el-table-column
 | ||
|         prop="StudyCode"
 | ||
|         :label="$t('trials:uploadedDicoms:table:studyId')"
 | ||
|         min-width="80"
 | ||
|         show-overflow-tooltip
 | ||
|       />
 | ||
|       <!-- 检查类型 -->
 | ||
|       <el-table-column
 | ||
|         prop="ModalityForEdit"
 | ||
|         :label="$t('trials:audit:table:modality')"
 | ||
|       />
 | ||
|       <!-- 检查设备 -->
 | ||
|       <el-table-column
 | ||
|         prop="Modalities"
 | ||
|         :label="$t('trials:audit:table:modality1')"
 | ||
|       />
 | ||
|       <!-- 检查部位 -->
 | ||
|       <el-table-column
 | ||
|         prop="BodyPartForEdit"
 | ||
|         :label="$t('trials:uploadedDicoms:table:bodyPart')"
 | ||
|         min-width="100"
 | ||
|         show-overflow-tooltip
 | ||
|       >
 | ||
|         <template slot-scope="scope">
 | ||
|           {{ getBodyPart(scope.row.BodyPartForEdit)}}
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
|       <!-- 序列数量 -->
 | ||
|       <el-table-column
 | ||
|         prop="SeriesCount"
 | ||
|         :label="$t('trials:uploadedDicoms:table:seriesCount')"
 | ||
|         min-width="100"
 | ||
|         show-overflow-tooltip
 | ||
|       />
 | ||
|       <!-- 图像数量 -->
 | ||
|       <el-table-column
 | ||
|         prop="InstanceCount"
 | ||
|         :label="$t('trials:uploadedDicoms:table:instanceCount')"
 | ||
|         min-width="100"
 | ||
|         show-overflow-tooltip
 | ||
|       />
 | ||
|       <!-- 检查日期 -->
 | ||
|       <el-table-column
 | ||
|         prop="StudyTime"
 | ||
|         :label="$t('trials:uploadedDicoms:table:studyDate')"
 | ||
|         min-width="120"
 | ||
|         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="UploadedTime"
 | ||
|         :label="$t('trials:uploadedDicoms:table:uploadedTime')"
 | ||
|         min-width="80"
 | ||
|         show-overflow-tooltip
 | ||
|       />
 | ||
|       <el-table-column :label="$t('common:action:action')" min-width="100" fixed="right">
 | ||
|         <template slot-scope="scope">
 | ||
|           <!-- 预览 -->
 | ||
|           <el-button
 | ||
|             icon="el-icon-view"
 | ||
|             :disabled="scope.row.SeriesCount === 0 || scope.row.IsDeleted"
 | ||
|             :title="$t('trials:uploadedDicoms:action:preview')"
 | ||
|             circle
 | ||
|             @click="handleViewStudy(scope.row)"
 | ||
|           />
 | ||
|           <!-- 编辑 -->
 | ||
|           <el-button
 | ||
|             icon="el-icon-edit-outline"
 | ||
|             v-hasPermi="['trials:trials-panel:visit:crc-upload:upload']"
 | ||
|             :title="$t('common:button:edit')"
 | ||
|             circle
 | ||
|             :disabled="scope.row.IsDeleted"
 | ||
|             @click="handleEditStudy(scope.row)"
 | ||
|           />
 | ||
|           <!-- 删除 -->
 | ||
|           <el-button
 | ||
|             icon="el-icon-delete"
 | ||
|             :disabled="scope.row.IsDeleted"
 | ||
|             :title="$t('trials:uploadedDicoms:action:delete')"
 | ||
|             circle
 | ||
|             @click="handleDeleteStudy(scope.row)"
 | ||
|           />
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
|     </el-table>
 | ||
| 
 | ||
|     <!-- 多文件上传 -->
 | ||
|     <form id="inputForm" ref="uploadForm" enctype="multipart/form-data">
 | ||
|       <el-divider content-position="left">{{ $t('trials:uploadedDicoms:title:dicomFilesOnly') }}</el-divider>
 | ||
|       <div class="form-group">
 | ||
|         <div id="directoryInputWrapper" class="btn btn-link file-input">
 | ||
|           <el-button type="primary" size="small">{{ $t('trials:uploadedDicomsicom:button:selectFolder') }}</el-button>
 | ||
|           <input
 | ||
|             type="file"
 | ||
|             name="file"
 | ||
|             webkitdirectory
 | ||
|             multiple
 | ||
|             @change="beginScanFiles($event)"
 | ||
|           >
 | ||
|         </div>
 | ||
|       </div>
 | ||
|     </form>
 | ||
| 
 | ||
|     <!-- 文件列表 -->
 | ||
|     <el-table
 | ||
|       ref="dicomFilesTable"
 | ||
|       :data="uploadQueues"
 | ||
|       class="dicomFiles-table"
 | ||
|       @selection-change="handleSelectionChange"
 | ||
|     >
 | ||
|       <el-table-column
 | ||
|         type="selection"
 | ||
|         width="55"
 | ||
|         :selectable="handleSelectable"
 | ||
|       />
 | ||
|       <el-table-column
 | ||
|         type="index"
 | ||
|         width="40"
 | ||
|       />
 | ||
|       <el-table-column min-width="200" show-overflow-tooltip>
 | ||
|         <template slot="header">
 | ||
|           <el-tooltip placement="top">
 | ||
|             <div slot="content">
 | ||
|               {{ $t('trials:uploadDicomList:table:studyDetail1') }}<br>
 | ||
|               {{ $t('trials:uploadDicomList:table:studyDetail2') }}<br>
 | ||
|               {{ $t('trials:uploadedDicoms:table:studyDate') }}
 | ||
|             </div>
 | ||
|             <span>{{ $t('trials:uploadDicomList:table:studyInfo') }}</span>
 | ||
|           </el-tooltip>
 | ||
|         </template>
 | ||
|         <template slot-scope="scope">
 | ||
|           <div style="line-height:15px;">
 | ||
|             <div>
 | ||
|               <div>
 | ||
|                 <span v-if="scope.row.dicomInfo.accNumber"><span style="font-weight:500;">Acc:</span> {{ scope.row.dicomInfo.accNumber }}</span>
 | ||
|                 <span v-else style="color:#f44336;">N/A</span>
 | ||
|               </div>
 | ||
|               <div style="display: inline-block;margin-right:2px">
 | ||
|                 <span v-if="scope.row.dicomInfo.modality.length>0"> {{ scope.row.dicomInfo.modality.join('、') }},</span>
 | ||
|                 <span v-else style="color:#f44336;">N/A,</span>
 | ||
|               </div>
 | ||
|               <div style="display: inline-block;margin-right:2px">
 | ||
|                 <span v-if="scope.row.seriesList.length">{{ scope.row.seriesList.length }} Series,</span>
 | ||
|                 <span v-else style="color:#f44336;">N/A,</span>
 | ||
|               </div>
 | ||
|               <div style="display: inline-block;">
 | ||
|                 <span v-if="scope.row.fileList.length">{{ scope.row.fileList.length }} Instances</span>
 | ||
|                 <span v-else style="color:#f44336;">N/A</span>
 | ||
|               </div>
 | ||
|             </div>
 | ||
| 
 | ||
|             <div>
 | ||
|               <div style="display: inline-block;margin-right:2px">
 | ||
|                 <span v-if="scope.row.dicomInfo.bodyPart">
 | ||
|                   {{ scope.row.dicomInfo.bodyPart }},
 | ||
|                 </span>
 | ||
|                 <span v-else style="color:#f44336;">N/A, </span>
 | ||
|               </div>
 | ||
|               <div style="display: inline-block;">
 | ||
|                 <span v-if="scope.row.dicomInfo.description">
 | ||
|                   {{ scope.row.dicomInfo.description }}</span>
 | ||
|                 <span v-else style="color:#f44336;">N/A</span>
 | ||
|               </div>
 | ||
|             </div>
 | ||
|             <div>
 | ||
|               {{ scope.row.dicomInfo.studyTime }}
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
| 
 | ||
|       <el-table-column min-width="130" show-overflow-tooltip>
 | ||
|         <template slot="header">
 | ||
|           <el-tooltip placement="top">
 | ||
|             <div slot="content">
 | ||
|               {{ $t('trials:uploadDicomList:table:pId') }}<br>
 | ||
|               {{ $t('trials:uploadDicomList:table:patientName') }}<br>
 | ||
|               {{ $t('trials:uploadDicomList:table:pInfo') }}
 | ||
|             </div>
 | ||
|             <span>{{ $t('trials:uploadDicomList:table:patientInfo') }}</span>
 | ||
|           </el-tooltip>
 | ||
|         </template>
 | ||
|         <template slot-scope="scope">
 | ||
|           <div style="line-height:15px;">
 | ||
|             <div>
 | ||
|               <span v-if="scope.row.dicomInfo.patientId"><span style="font-weight:500;">PID: </span>{{ scope.row.dicomInfo.patientId }}</span>
 | ||
|               <span v-else style="color:#f44336;">N/A</span>
 | ||
|             </div>
 | ||
|             <div>
 | ||
|               <span :class="[scope.row.dicomInfo.patientName?'':'colorOfRed']">
 | ||
|                 {{ scope.row.dicomInfo.patientName?scope.row.dicomInfo.patientName:'N/A' }}
 | ||
|               </span>
 | ||
|             </div>
 | ||
|             <div>
 | ||
|               <span :class="[scope.row.dicomInfo.patientSex?'':'colorOfRed']">
 | ||
|                 {{ scope.row.dicomInfo.patientSex?scope.row.dicomInfo.patientSex:'N/A' }},
 | ||
|               </span>
 | ||
| 
 | ||
|               <span :class="[scope.row.dicomInfo.patientAge?'':'colorOfRed']">
 | ||
|                 {{ scope.row.dicomInfo.patientAge?scope.row.dicomInfo.patientAge:'N/A' }},
 | ||
|               </span>
 | ||
| 
 | ||
|               <span :class="[scope.row.dicomInfo.patientBirthDate?'':'colorOfRed']">
 | ||
|                 {{ scope.row.dicomInfo.patientBirthDate?scope.row.dicomInfo.patientBirthDate:'N/A' }}
 | ||
|               </span>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
|       <el-table-column :label="$t('trials:uploadDicomList:table:status')" min-width="120" show-overflow-tooltip>
 | ||
|         <template slot-scope="scope">
 | ||
| <!--          <el-progress v-show="scope.row.uploadState.progressValue && scope.row.uploadState.progressValue!= 100" :percentage="scope.row.uploadState.progressValue" />-->
 | ||
|           <el-progress v-show="scope.row.uploadState.stateText" :percentage="scope.row.uploadState.progressValue" />
 | ||
| <!--          <el-progress v-show="scope.row.uploadState.UpdataValue && scope.row.uploadState.UpdataValue!= 100" color="#409eff" :format="format(scope.row.uploadState.UpdataValue)" :percentage="scope.row.uploadState.UpdataValue" />-->
 | ||
|           <el-progress v-show="scope.row.uploadState.stateText" color="#409eff" :format="format(scope.row.uploadState.UpdataValue)" :percentage="scope.row.uploadState.UpdataValue" />
 | ||
|           <el-tooltip v-if="scope.row.uploadState.stateCode === 'Uploading not allowed'" class="item" effect="dark" :content="scope.row.uploadState.errorMessage" placement="bottom">
 | ||
|             <span>{{ scope.row.uploadState.stateText }}</span>
 | ||
|           </el-tooltip>
 | ||
| 
 | ||
|           <span v-else>{{ scope.row.uploadState.stateText }}</span>
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
| 
 | ||
|       <el-table-column
 | ||
|         :label="$t('trials:uploadDicomList:table:stats')"
 | ||
|         min-width="140"
 | ||
|         show-overflow-tooltip
 | ||
|       >
 | ||
|         <template slot-scope="scope">
 | ||
|           <div style="display: flex;justify-content: flex-start;align-items: center">
 | ||
|             <div
 | ||
|               v-if="scope.row.uploadState.totalCount"
 | ||
|               style="text-align: center"
 | ||
|             >
 | ||
|               {{
 | ||
|                 scope.row.uploadState.totalCount +
 | ||
|                   ' / ' +
 | ||
|                   scope.row.uploadState.successCount +
 | ||
|                   ' / ' +
 | ||
|                   scope.row.uploadState.failedCount
 | ||
|               }}
 | ||
|             </div>
 | ||
|             <div v-if="scope.row.uploadState.failedCount > 0">
 | ||
|               <el-button
 | ||
|                 type="primary"
 | ||
|                 size="small"
 | ||
|                 @click="exportFailedFiles(scope.row.uploadState.ErrorFiles)"
 | ||
|               >
 | ||
|                 {{ $t('trials:uploadDicomList:button:exportFailed') }}
 | ||
|               </el-button>
 | ||
|             </div>
 | ||
|           </div>
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
| 
 | ||
|       <el-table-column v-show="isScan" :label="$t('common:action:action')" width="200">
 | ||
|         <template slot-scope="scope">
 | ||
|           <!-- 预览 -->
 | ||
|           <el-button
 | ||
|             icon="el-icon-view"
 | ||
|             circle
 | ||
|             :title="$t('trials:uploadedDicoms:action:preview')"
 | ||
|             size="small"
 | ||
|             @click="handlePreview(scope.row.dicomInfo.studyUid)"
 | ||
|           />
 | ||
|           <!-- 移除 -->
 | ||
|           <el-button
 | ||
|             icon="el-icon-delete"
 | ||
|             circle
 | ||
|             :title="$t('trials:uploadedDicoms:action:delete')"
 | ||
|             size="small"
 | ||
|             :disabled="scope.row.uploadState.stateCode !== ''"
 | ||
|             @click="handleDelete(scope.$index, scope.row)"
 | ||
|           />
 | ||
|         </template>
 | ||
|       </el-table-column>
 | ||
|     </el-table>
 | ||
|     <div style="text-align:right;padding: 10px 0px">
 | ||
|       <!-- 关闭 -->
 | ||
|       <!-- <el-button :disabled="btnLoading" size="small" type="primary" @click="cancel">
 | ||
|         {{ $t('trials:uploadDicomList:button:close') }}
 | ||
|       </el-button> -->
 | ||
|       <!-- 上传 -->
 | ||
|       <el-button
 | ||
|         size="small"
 | ||
|         type="primary"
 | ||
|         :disabled="selectArr.length == 0 || !isScan"
 | ||
|         :loading="btnLoading || uploadCount !== uploadedCount"
 | ||
|         @click="beginUploadQueues"
 | ||
|       >
 | ||
|         {{ $t('trials:uploadDicomList:button:upload') }}
 | ||
|       </el-button>
 | ||
|     </div>
 | ||
| 
 | ||
|     <!-- 预览影像模态框 -->
 | ||
|     <el-dialog
 | ||
|       v-if="previewVisible"
 | ||
|       :fullscreen="true"
 | ||
|       :show-close="true"
 | ||
|       :visible.sync="previewVisible"
 | ||
|       append-to-body
 | ||
|     >
 | ||
|       <DicomPreview :uid="uid" />
 | ||
|     </el-dialog>
 | ||
| 
 | ||
|     <!-- 校验警告信息模态框 -->
 | ||
|     <el-dialog
 | ||
|       v-if="warning_cfg.visible"
 | ||
|       :visible.sync="warning_cfg.visible"
 | ||
|       width="500px"
 | ||
|       :close-on-click-modal="false"
 | ||
|       append-to-body
 | ||
|       title="Warning"
 | ||
|       custom-class="warning-dialog"
 | ||
|     >
 | ||
|       <div style="border:1px solid #e0e0e0;padding:10px;">
 | ||
|         <!-- Information from DICOM headers not consistent with that of this subject -->
 | ||
|         <div style="color: red;font-size:14px;margin-bottom:10px;">
 | ||
|           {{ $t('trials:uploadDicomList:message:informationConsistent') }}:
 | ||
|         </div>
 | ||
|         <div v-for="(item,i) in warningArr" :key="item.index">
 | ||
|           <div>{{ `(${i+1}). ACC: ${item.accNumber}` }}</div>
 | ||
|           <div v-for="(warning,index) in item.warnings" :key="index" style="margin:10px 0px;font-size:13px;">
 | ||
|             <ul>
 | ||
|               <li>{{ warning }}</li>
 | ||
|             </ul>
 | ||
|           </div>
 | ||
|         </div>
 | ||
|       </div>
 | ||
|       <div slot="footer" class="base-modal-footer">
 | ||
|         <el-button size="small" type="primary" @click="handleCancelWarnVisible">
 | ||
|           {{ $t('common:button:cancel') }}
 | ||
|         </el-button>
 | ||
|         <el-button size="small" type="primary" @click="handleContinueUpload">
 | ||
|           {{ $t('trials:uploadDicomList:button:upload') }}
 | ||
|         </el-button>
 | ||
|       </div>
 | ||
|     </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="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)}}</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>
 | ||
|   </div>
 | ||
| 
 | ||
| </template>
 | ||
| <script>
 | ||
| import {
 | ||
|   batchVerifyStudyAllowUpload, getSubjectVisitUploadedStudyList, deleteStudyList, updateModality, preArchiveStudy
 | ||
| } from '@/api/trials'
 | ||
| import store from '@/store'
 | ||
| import * as dicomParser from 'dicom-parser'
 | ||
| import * as signalR from '@microsoft/signalr'
 | ||
| import DicomPreview from '@/views/dicom-show/dicom-preview'
 | ||
| import dicomStore from '@/utils/dicom-store'
 | ||
| import { getToken } from '@/utils/auth'
 | ||
| import moment from 'moment'
 | ||
| export default {
 | ||
|   name: 'UploadDicomFiles',
 | ||
|   components: { DicomPreview },
 | ||
|   props: {
 | ||
|     data: {
 | ||
|       type: Object,
 | ||
|       default() {
 | ||
|         return {}
 | ||
|       }
 | ||
|     },
 | ||
|     subjectVisitId: {
 | ||
|       type: String,
 | ||
|       required: true
 | ||
|     },
 | ||
|     subjectId: {
 | ||
|       type: String,
 | ||
|       required: true
 | ||
|     }
 | ||
|   },
 | ||
|   data() {
 | ||
|     return {
 | ||
|       editStudyInfoVisible: false,
 | ||
|       studyForm: { StudyCode: '', IsDicomData: true, Modalities: '', BodyPartForEdit: [], SeriesCount: null, StudyTime: '' },
 | ||
|       uploadQueues: dicomStore.studyList, // 上传队列
 | ||
|       selectArr: [], // 已勾选待上传文件
 | ||
|       scanState: '', // 当前上传队列上传状态
 | ||
|       form: {
 | ||
|         SiteName: '',
 | ||
|         SubjectName: '',
 | ||
|         VisitName: '',
 | ||
|         SubjectId: '',
 | ||
|         VisitNum: null
 | ||
|       },
 | ||
|       btnLoading: false,
 | ||
|       previewVisible: false,
 | ||
|       warning_cfg: { visible: false },
 | ||
|       warningArr: [],
 | ||
|       isScan: false,
 | ||
|       studyLoading: false,
 | ||
|       studyList: [],
 | ||
|       deleteArr: [],
 | ||
|       trialId: '',
 | ||
|       moment,
 | ||
|       uploadCount: 0,
 | ||
|       uploadedCount: 0,
 | ||
|       wsList: [],
 | ||
|       relationInfo: null,
 | ||
|       trialBodyPartTypes: [],
 | ||
|       trialModalitys: [],
 | ||
|     }
 | ||
|   },
 | ||
|   mounted() {
 | ||
|     this.trialId = this.$route.query.trialId
 | ||
|     if (Object.keys(this.data).length) {
 | ||
|       this.form = { ...this.data }
 | ||
|     }
 | ||
|     let connection = new signalR.HubConnectionBuilder()
 | ||
|       .withUrl("/UploadHub", { accessTokenFactory: () => getToken() })
 | ||
|       .configureLogging(signalR.LogLevel.Information)
 | ||
|       .withAutomaticReconnect()
 | ||
|       .build()
 | ||
|     connection.start()
 | ||
|     connection.on("ReceivProgressAsync", (id, num) => {
 | ||
|       this.onUploadProgress2(id, num)
 | ||
|     });
 | ||
|     this.getStudyInfo()
 | ||
|   },
 | ||
|   methods: {
 | ||
|     // 打开检查信息编辑框
 | ||
|     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.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
 | ||
|         }
 | ||
|         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 })
 | ||
|       })
 | ||
|     },
 | ||
|     format(v) {
 | ||
|       return v
 | ||
|     },
 | ||
|     // 获取已上传的dicom影像
 | ||
|     getStudyInfo() {
 | ||
|       this.studyLoading = true
 | ||
|       getSubjectVisitUploadedStudyList(this.subjectVisitId).then(res => {
 | ||
|         this.studyList = res.Result
 | ||
|         this.relationInfo = res.OtherInfo
 | ||
|         this.trialBodyPartTypes =
 | ||
|           this.relationInfo.BodyPartTypes ? this.relationInfo.BodyPartTypes.split('|') : []
 | ||
|         this.trialModalitys =
 | ||
|           this.relationInfo.Modalitys ? this.relationInfo.Modalitys.split('|') : []
 | ||
|         this.studyLoading = false
 | ||
|       }).catch(() => { this.studyLoading = false })
 | ||
|     },
 | ||
|     // 预览单个检查影像
 | ||
|     handleViewStudy(row) {
 | ||
|       var token = getToken()
 | ||
|       const routeData = this.$router.resolve({
 | ||
|         path: `/showdicom?studyId=${row.StudyId}&TokenKey=${token}&type=Study`
 | ||
|       })
 | ||
|       window.open(routeData.href, '_blank')
 | ||
|     },
 | ||
|     // 预览所有影像
 | ||
|     handlePreviewAllFiles() {
 | ||
|       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}&TokenKey=${token}`
 | ||
|       })
 | ||
|       window.open(routeData.href, '_blank')
 | ||
|     },
 | ||
|     // 扫描待上传文件
 | ||
|     beginScanFiles(e) {
 | ||
|       var files = e.target.files
 | ||
|       if (files.length > 0) {
 | ||
|         console.log(files)
 | ||
|         var checkFiles = [...files]
 | ||
|         // var isHasDicom = checkFiles.find(v => {
 | ||
|         //   return v.name.split('.')[v.name.split('.').length - 1] === 'DCM' || v.name.split('.')[v.name.split('.').length - 1] === 'dcm'
 | ||
|         // })
 | ||
|         // if (!isHasDicom) {
 | ||
|         //   this.$message.error(this.$t('trials:trials-panel:message:notIsHasDicom'))
 | ||
|         // }
 | ||
|         var scope = this
 | ||
|         scope.scanState = ''
 | ||
|         scope.isScan = false
 | ||
|         var p = new Promise(function(resolve) {
 | ||
|           resolve()
 | ||
|         })
 | ||
|         for (var i = 0; i < files.length; ++i) {
 | ||
|           (function(index) {
 | ||
|             p = p.then(function() {
 | ||
|               return scope.parseDicomFile(files[index])
 | ||
|             })
 | ||
|           })(i)
 | ||
|         }
 | ||
|         p.then(function(result) {
 | ||
|           scope.scanState = 'finished'
 | ||
|           scope.isScan = true
 | ||
|         })
 | ||
|       }
 | ||
|     },
 | ||
|     // 按序列UUID本地归档
 | ||
|     parseDicomFile(file) {
 | ||
|       var scope = this
 | ||
|       return new Promise(function(resolve, reject) {
 | ||
|         if (scope.scanState === 'cancelling') {
 | ||
|           resolve()
 | ||
|           return
 | ||
|         }
 | ||
|         var reader = new FileReader()
 | ||
|         reader.onload = function(e) {
 | ||
|           try {
 | ||
|             var data = dicomParser.parseDicom(new Uint8Array(e.target.result))
 | ||
|             var studyUid = data.string('x0020000d')
 | ||
|             var studyIndex = 0
 | ||
|             while (
 | ||
|               studyIndex < scope.uploadQueues.length &&
 | ||
|               scope.uploadQueues[studyIndex].dicomInfo.studyUid !== studyUid
 | ||
|             ) {
 | ||
|               ++studyIndex
 | ||
|             }
 | ||
|             if (studyIndex >= scope.uploadQueues.length) {
 | ||
|               var date = data.string('x00080020')
 | ||
|               var time = data.string('x00080030')
 | ||
|               var studyTime = ''
 | ||
|               if (date) {
 | ||
|                 // date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
 | ||
|                 date = `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`
 | ||
|               }
 | ||
|               if (time) {
 | ||
|                 // time = `${time.substr(0, 2)}:${time.substr(2, 2)}:${time.substr(4, 2)}`
 | ||
|                 time = `${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}`
 | ||
|               }
 | ||
|               if(date){
 | ||
|                 studyTime = time ? `${date} ${time}` : `${date} 00:00:00`
 | ||
|               }
 | ||
|               scope.uploadQueues.push({
 | ||
|                 studyIndex: studyIndex,
 | ||
|                 seriesList: [],
 | ||
|                 fileList: [],
 | ||
|                 dicomInfo: {
 | ||
|                   studyUid: studyUid,
 | ||
|                   patientId: data.string('x00100020'),
 | ||
|                   patientName: data.string('x00100010') ? data.string('x00100010') : '',
 | ||
|                   patientAge: data.string('x00101010') ? data.string('x00101010') : '',
 | ||
|                   patientSex: data.string('x00100040') ? data.string('x00100040') : '',
 | ||
|                   patientBirthDate: data.string('x00100030'),
 | ||
|                   hospitalName: data.string('x00080080'),
 | ||
|                   accNumber: data.string('x00080050'),
 | ||
|                   bodyPart: data.string('x00180015'),
 | ||
|                   modality: [],
 | ||
|                   institutionName: data.string('x00080080'),
 | ||
|                   description: data.string('x00081030'),
 | ||
|                   studyTime: studyTime,
 | ||
|                   VisitInfo: {},
 | ||
|                   SubjectInfo: {}
 | ||
|                 },
 | ||
| 
 | ||
|                 uploadState: {
 | ||
|                   selected: false,
 | ||
|                   stateCode: '',
 | ||
|                   beginUploadTime: {},
 | ||
|                   progressValue: 0
 | ||
|                 }
 | ||
|               })
 | ||
|             }
 | ||
|             var modality = scope.uploadQueues[studyIndex].dicomInfo.modality
 | ||
|             var currentModality = data.string('x00080060')
 | ||
|             if (!(modality.indexOf(currentModality) > -1)) {
 | ||
|               modality.push(currentModality)
 | ||
|             }
 | ||
| 
 | ||
|             var fileList = scope.uploadQueues[studyIndex].fileList
 | ||
|             var instanceUid = data.string('x00080018')
 | ||
|             var instanceIndex = 0
 | ||
|             while (
 | ||
|               instanceIndex < fileList.length &&
 | ||
|               fileList[instanceIndex].instanceUid !== instanceUid
 | ||
|             ) {
 | ||
|               ++instanceIndex
 | ||
|             }
 | ||
|             if (instanceIndex >= fileList.length) {
 | ||
|               fileList.push({
 | ||
|                 instanceUid: instanceUid,
 | ||
|                 file: file
 | ||
|               })
 | ||
|             }
 | ||
| 
 | ||
|             var seriesUid = data.string('x0020000e')
 | ||
|             var seriesList = scope.uploadQueues[studyIndex].seriesList
 | ||
|             var seriesItem = seriesList.find(function(item) {
 | ||
|               return item.seriesUid === seriesUid
 | ||
|             })
 | ||
|             if (!seriesItem) {
 | ||
|               seriesItem = {
 | ||
|                 seriesUid: seriesUid,
 | ||
|                 seriesNumber: data.intString('x00200011') || 1,
 | ||
|                 modality: data.string('x00080060'),
 | ||
|                 description: data.string('x0008103e'),
 | ||
|                 instanceList: []
 | ||
|               }
 | ||
|               seriesList.push(seriesItem)
 | ||
|             }
 | ||
|             var instanceList = seriesItem.instanceList
 | ||
|             var instanceItem = instanceList.find(function(item) {
 | ||
|               return item.instanceUid === instanceUid
 | ||
|             })
 | ||
|             if (!instanceItem) {
 | ||
|               instanceItem = {
 | ||
|                 instanceUid: instanceUid,
 | ||
|                 instanceNumber: data.intString('x00200013') || 1,
 | ||
|                 frameCount: data.intString('x00280008') || 1,
 | ||
|                 file: file
 | ||
|               }
 | ||
|               instanceList.push(instanceItem)
 | ||
|             }
 | ||
| 
 | ||
|             resolve()
 | ||
|           } catch (error) {
 | ||
|             // scope.$message.error(scope.$t('trials:trials-panel:message:notIsHasDicom'))
 | ||
|             console.log(error)
 | ||
|             resolve()
 | ||
|           }
 | ||
|         }
 | ||
|         reader.onerror = function(e) {
 | ||
|           resolve()
 | ||
|         }
 | ||
|         reader.readAsArrayBuffer(file)
 | ||
|       })
 | ||
|     },
 | ||
|     // 上传之前校验基本信息及检查是否已上传
 | ||
|     beginUploadQueues() {
 | ||
|       this.scanState = 'uploading'
 | ||
|       this.warningArr = []
 | ||
|       for (let i = 0; i < this.selectArr.length; ++i) {
 | ||
|         const index = this.selectArr[i].studyIndex
 | ||
|         this.uploadQueues[index].uploadState.stateCode = 'uploading'
 | ||
|         this.verifyBasicInfos(index)
 | ||
|       }
 | ||
|       if (this.warningArr.length) {
 | ||
|         this.warning_cfg.visible = true
 | ||
|       } else {
 | ||
|         this.verifyStudy()
 | ||
|       }
 | ||
|     },
 | ||
|     // 校验影像中检查时间、性别是否与受试者匹配
 | ||
|     verifyBasicInfos(index) {
 | ||
|       // const studyTime = moment(this.uploadQueues[index].dicomInfo.studyTime).format('YYYY-MM-DD')
 | ||
|       var warnings = []
 | ||
|       // if (studyTime && studyTime < this.form.SVSTDTC) {
 | ||
|       //   warnings.push('Study Date earlier than Visit Start Date.')
 | ||
|       // }
 | ||
|       // if (studyTime && studyTime > this.form.SVSTDTC) {
 | ||
|       //   if (this.compare(studyTime, this.form.SVSTDTC) > 7) { warnings.push('Study Date later than Visit Start Date for more than one week.') }
 | ||
|       // }
 | ||
|       // const patientAge = this.uploadQueues[index].dicomInfo.patientAge
 | ||
|       // if (patientAge && this.form.SubjectAge) {
 | ||
|       //   var age = patientAge.match(/\d+(.\d+)?/g)
 | ||
|       //   if (Math.abs(parseInt(age[0]) - parseInt(this.form.SubjectAge)) >= 1) {
 | ||
|       //     warnings.push('Patient Age not consistent with Subject Age.')
 | ||
|       //   }
 | ||
|       // }
 | ||
|       if (this.uploadQueues[index].dicomInfo.patientSex && this.form.SubjectSex) {
 | ||
|         if (this.uploadQueues[index].dicomInfo.patientSex.substr(0, 1) !== this.form.SubjectSex.substr(0, 1)) {
 | ||
|           warnings.push(this.$t('trials:uploadDicomList:message:genderConsistent'))
 | ||
|         }
 | ||
|       }
 | ||
|       if (warnings.length > 0) {
 | ||
|         this.warningArr.push({ index: this.uploadQueues[index].studyIndex + 1, accNumber: this.uploadQueues[index].dicomInfo.accNumber, warnings: warnings })
 | ||
|       }
 | ||
|     },
 | ||
|     // 校验该检查是否上传过
 | ||
|     verifyStudy() {
 | ||
|       this.btnLoading = true
 | ||
|       var studyList = []
 | ||
|       this.selectArr.forEach(item => {
 | ||
|         studyList.push({ studyInstanceUid: item.dicomInfo.studyUid, studyDate: item.dicomInfo.studyTime })
 | ||
|       })
 | ||
| 
 | ||
|       var param = {
 | ||
|         trialId: this.trialId,
 | ||
|         subjectId: this.subjectId,
 | ||
|         subjectVisitId: this.subjectVisitId,
 | ||
|         visitNum: this.form.VisitNum,
 | ||
|         studyInstanceUidList: studyList
 | ||
|       }
 | ||
|       batchVerifyStudyAllowUpload(param).then((res) => {
 | ||
|         var messageArr = []
 | ||
|         res.Result.forEach((item) => {
 | ||
|           // 不能上传或不能重传时,收集校验结果提示,并取消勾选,设置上传状态
 | ||
|           if (item.ErrorMesseage) {
 | ||
|             const i = this.uploadQueues.findIndex((value) => value.dicomInfo.studyUid === item.StudyInstanceUid)
 | ||
|             // Uploading not allowed
 | ||
|             this.uploadQueues[i].uploadState.stateText = this.$t('trials:uploadDicomList:label:uploadingNotAllowed')
 | ||
|             this.uploadQueues[i].uploadState.selected = true
 | ||
|             this.uploadQueues[i].uploadState.stateCode = 'Uploading not allowed'
 | ||
|             this.uploadQueues[i].uploadState.errorMessage = item.ErrorMesseage
 | ||
|             this.$refs.dicomFilesTable.toggleRowSelection(this.uploadQueues[i])
 | ||
|             // const msg = `ACC:${this.uploadQueues[i].dicomInfo.accNumber}, ${item.ErrorMesseage}`
 | ||
|             const msg = `${item.ErrorMesseage}`
 | ||
|             messageArr.push(msg)
 | ||
|           }
 | ||
| 
 | ||
|           // 可以重传时,记录需要被覆盖的检查ID
 | ||
|           if (item.AllowReUpload) {
 | ||
|             const i = this.uploadQueues.findIndex((value) => value.dicomInfo.studyUid === item.StudyInstanceUid)
 | ||
|             this.uploadQueues[i].AbandonStudyId = item.StudyInfo ? item.StudyInfo.Id : ''
 | ||
|           }
 | ||
|         })
 | ||
| 
 | ||
|         if (messageArr.length > 0) {
 | ||
|           var li = messageArr.map(msg => { return `<li>${msg}</li>` })
 | ||
|           const content = `
 | ||
|                         <div>
 | ||
|                         <ol>
 | ||
|                         ${li.join('')}
 | ||
|                         </ol>
 | ||
|                         </div>`
 | ||
|           this.$alert(content, this.$t('trials:uploadDicomList:label:prompt'),
 | ||
|             {
 | ||
|               confirmButtonText: this.$t('trials:uploadDicomList:label:confirm'),
 | ||
|               dangerouslyUseHTMLString: true,
 | ||
|               callback: (action) => {}
 | ||
|             })
 | ||
|           this.btnLoading = false
 | ||
|         }
 | ||
|         var results = []
 | ||
|         this.uploadCount = this.selectArr.length
 | ||
|         this.uploadedCount = 0
 | ||
|         for (let i = 0; i < this.selectArr.length; ++i) {
 | ||
|           const index = this.selectArr[i].studyIndex
 | ||
|           results.push(this.archiveStudy(index))
 | ||
|         }
 | ||
|         Promise.all(results).then(_ => {
 | ||
|           this.btnLoading = false
 | ||
|         }).catch(_ => {
 | ||
|           this.btnLoading = false
 | ||
|         })
 | ||
|       }).catch(_ => { this.btnLoading = false })
 | ||
|     },
 | ||
|     objectToQuery() {
 | ||
|       let obj = arguments[0]
 | ||
|       let prefix = arguments[1]
 | ||
|       if (typeof obj !== 'object') return ''
 | ||
|       const attrs = Object.keys(obj)
 | ||
|       return attrs.reduce((query, attr, index) => {
 | ||
|         // 判断是否是第一层第一个循环
 | ||
|         if (index === 0 && !prefix) query += '?'
 | ||
|         if (typeof obj[attr] === 'object') {
 | ||
|           const subPrefix = prefix ? `${prefix}[${attr}]` : attr
 | ||
|           query += this.objectToQuery(obj[attr], subPrefix)
 | ||
|         } else {
 | ||
|           if (prefix) {
 | ||
|             query += `${prefix}[${attr}]=${obj[attr]}`
 | ||
|           } else {
 | ||
|             query += `${attr}=${obj[attr]}`
 | ||
|           }
 | ||
|         }
 | ||
|         // 判断是否是第一层最后一个循环
 | ||
|         if (index !== attrs.length - 1) query += '&'
 | ||
|         return query
 | ||
|       }, '')
 | ||
|     },
 | ||
|     // 上传影像并归档
 | ||
|     archiveStudy(index) {
 | ||
|       var scope = this
 | ||
|       return new Promise(function(resolve, reject) {
 | ||
|         preArchiveStudy({
 | ||
|           subjectVisitId: scope.subjectVisitId,
 | ||
|           isDicom: true
 | ||
|         }).then(res => {
 | ||
|           var data = new FormData()
 | ||
|           var dicomInfo = scope.uploadQueues[index].dicomInfo
 | ||
|           var seriesNum = scope.uploadQueues[index].seriesList.length
 | ||
|           var fileNum = scope.uploadQueues[index].fileList.length
 | ||
|           dicomInfo.seriesNum = seriesNum
 | ||
|           dicomInfo.fileNum = fileNum
 | ||
|           dicomInfo.siteId = scope.data.SiteId
 | ||
|           dicomInfo.subjectId = scope.data.SubjectId
 | ||
|           dicomInfo.subjectVisitId = scope.subjectVisitId
 | ||
|           var params = {
 | ||
|             trialId: scope.trialId,
 | ||
|             subjectVisitId: scope.subjectVisitId,
 | ||
|             studyInstanceUid: scope.uploadQueues[index].dicomInfo.studyUid,
 | ||
|             StudyMonitorId: res.Result
 | ||
|           }
 | ||
|           // data.append('subjectVisitId', scope.subjectVisitId)
 | ||
|           // data.append('studyInstanceUid', scope.uploadQueues[index].dicomInfo.studyUid)
 | ||
|           if (scope.uploadQueues[index].AbandonStudyId) {
 | ||
|             params.abandonStudyId = scope.uploadQueues[index].AbandonStudyId
 | ||
|             // data.append('abandonStudyId', scope.uploadQueues[index].AbandonStudyId)
 | ||
|           }
 | ||
|           for (var i = 0; i < scope.uploadQueues[index].fileList.length; ++i) {
 | ||
|             data.append('file', scope.uploadQueues[index].fileList[i].file)
 | ||
|           }
 | ||
|           scope.btnLoading = true
 | ||
|           var xhr = new XMLHttpRequest()
 | ||
|           xhr.open('POST', `/api/study/archiveStudy${scope.objectToQuery(params)}`)
 | ||
|           xhr.setRequestHeader('Authorization', `Bearer ${store.getters.token}`)
 | ||
|           // xhr.setRequestHeader('Content-Type', 'multipart/form-data')
 | ||
|           // xhr.setRequestHeader('Content-Type', 'octet-stream')
 | ||
|           xhr.timeout = 2 * 360000 // 超时时间,单位是毫秒
 | ||
|           xhr.responseType = 'text'
 | ||
|           xhr.onload = function(e) {
 | ||
|             scope.onUploadCompleted(e, index)
 | ||
|             resolve()
 | ||
|           }
 | ||
|           xhr.onerror = function(e) {
 | ||
|             scope.onUploadError(e, index)
 | ||
|             resolve()
 | ||
|           }
 | ||
|           xhr.upload.onprogress = function(e) {
 | ||
|             scope.onUploadProgress(e, index)
 | ||
|           }
 | ||
|           // xhr.onprogress = function(e) {
 | ||
|           //   console.log('请求完成')
 | ||
|           //   scope.onUploadProgress(e, index)
 | ||
|           // }
 | ||
|           xhr.send(data)
 | ||
|           var uploadState = scope.uploadQueues[index].uploadState
 | ||
|           //  'Uploading...'
 | ||
|           uploadState.stateText = `${this.$t('trials:uploadDicomList:label:uploading')}...`
 | ||
| 
 | ||
|           uploadState.beginUploadTime = new Date()
 | ||
|           uploadState.progressValue = 0
 | ||
|         })
 | ||
|       })
 | ||
|     },
 | ||
|     // 上传成功回调
 | ||
|     onUploadCompleted: function(e, index) {
 | ||
|       this.uploadedCount++
 | ||
|       var uploadState = this.uploadQueues[index].uploadState
 | ||
|       // this.btnLoading = false
 | ||
| 
 | ||
|       if (e.target.status === 200) {
 | ||
|         const responseObj = JSON.parse(e.target.responseText)
 | ||
|         uploadState.stateCode = 'Finished'
 | ||
| 
 | ||
|         if (responseObj.IsSuccess) {
 | ||
|           this.uploadQueues[index].uploadState.selected = true
 | ||
|           const i = this.selectArr.findIndex(item => { item.studyIndex === index })
 | ||
|           this.selectArr.splice(i, 1)
 | ||
|           this.$refs.dicomFilesTable.toggleRowSelection(this.uploadQueues[index])
 | ||
|           uploadState.totalCount = responseObj.Result.ReceivedFileCount
 | ||
| 
 | ||
|           uploadState.failedCount = responseObj.Result.ErrorFiles.length
 | ||
|           uploadState.successCount = uploadState.totalCount - uploadState.failedCount
 | ||
|           uploadState.ErrorFiles = responseObj.Result.ErrorFiles
 | ||
|           if (responseObj.Result.ArchivedDicomStudies.length > 0) {
 | ||
|             // Uploaded
 | ||
|             // uploadState.stateText = this.$t('trials:uploadDicomList:label:uploaded')
 | ||
|             uploadState.stateText = this.$t('trials:uploadDicomList:label:uploaded')//'上传完成'
 | ||
|             this.scanState = 'Uploaded'
 | ||
|             this.getStudyInfo()
 | ||
|             this.$emit('getList')
 | ||
|           }
 | ||
|         } else {
 | ||
|           // Failed
 | ||
|           this.uploadQueues[index].uploadState.stateText = this.$t('trials:uploadDicomList:label:uploadFailed')
 | ||
|           this.scanState = 'Failed'
 | ||
|           if (responseObj.ErrorMessage) {
 | ||
|             this.$message.error(responseObj.ErrorMessage)
 | ||
|           }
 | ||
|         }
 | ||
|         this.wariningMes = ''
 | ||
|       } else {
 | ||
|         uploadState.stateCode = 'Failed'
 | ||
|         // Failed
 | ||
|         uploadState.stateText = this.$t('trials:uploadDicomList:label:uploadFailed')
 | ||
|         this.scanState = 'Failed'
 | ||
|       }
 | ||
|       this.$forceUpdate()
 | ||
|     },
 | ||
|     // 上传失败回调
 | ||
|     onUploadError: function(e, index) {
 | ||
|       this.uploadedCount++
 | ||
|       // this.btnLoading = false
 | ||
|       var uploadState = this.uploadQueues[index].uploadState
 | ||
|       uploadState.stateCode = 'Failed'
 | ||
|       uploadState.stateText = this.$t('trials:uploadDicomList:label:uploadFailed')
 | ||
|       this.scanState = 'Failed'
 | ||
|     },
 | ||
|     onUploadProgress2(id, num) {
 | ||
|       let info = this.uploadQueues.find(v => {
 | ||
|         return v.dicomInfo.studyUid === id
 | ||
|       })
 | ||
|       if (info && info.uploadState.stateText !== this.$t('trials:uploadDicomList:label:uploaded')) {
 | ||
|         // fileNum 总数
 | ||
|         this.$set(info.uploadState, 'UpdataValue', Math.floor(num / info.dicomInfo.fileNum * 100))
 | ||
|         this.$set(info.uploadState, 'stateText', this.$t('trials:uploadDicomList:message:archiveSuccess'))//`文件已上传成功,等待归档。归档完成后可查看影像数据,现在可以返回。`
 | ||
|         // this.$set(info.uploadState, 'stateText', '归档中')//`文件已上传成功,等待归档。归档完成后可查看影像数据,现在可以返回。`
 | ||
|       }
 | ||
|     },
 | ||
|     // 上传进程
 | ||
|     onUploadProgress: function(e, index) {
 | ||
|       if (e.lengthComputable) {
 | ||
|         var percent = Math.floor(e.loaded / e.total * 100)
 | ||
|         console.log(e.loaded, e.total, percent)
 | ||
|         // Uploading
 | ||
|         // this.uploadQueues[index].uploadState.stateText = `${this.$t('trials:uploadDicomList:label:uploading')}...`
 | ||
|         // this.uploadQueues[index].uploadState.progressValue = percent
 | ||
|         this.$set(this.uploadQueues[index].uploadState, 'stateText', this.$t('trials:uploadDicomList:label:uploading'))//`影像上传中`
 | ||
| 
 | ||
|         this.$set(this.uploadQueues[index].uploadState, 'progressValue', percent)
 | ||
|         // if (percent === 100) {
 | ||
|         //   this.uploadQueues[index].uploadState.progressValue = 100
 | ||
|         // }
 | ||
|         // this.$forceUpdate()
 | ||
|       }
 | ||
|     },
 | ||
|     // warning弹框取消按钮回调
 | ||
|     handleCancelWarnVisible() {
 | ||
|       this.warning_cfg.visible = false
 | ||
|       for (var i = 0; i < this.selectArr.length; ++i) {
 | ||
|         const index = this.selectArr[i].studyIndex
 | ||
|         this.uploadQueues[index].uploadState.stateCode = ''
 | ||
|       }
 | ||
|     },
 | ||
|     // 忽略warning继续上传
 | ||
|     handleContinueUpload() {
 | ||
|       this.warning_cfg.visible = false
 | ||
|       this.verifyStudy()
 | ||
|     },
 | ||
|     // 预览影像
 | ||
|     handlePreview(uid) {
 | ||
|       this.previewVisible = true
 | ||
|       this.uid = uid
 | ||
|     },
 | ||
|     // 删除影像列表中的某个影像
 | ||
|     handleDelete(index, row) {
 | ||
|       this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
 | ||
|         type: 'warning',
 | ||
|         distinguishCancelAndClose: true
 | ||
|       })
 | ||
|         .then(() => {
 | ||
|           this.$refs.uploadForm.reset()
 | ||
|           this.selectArr = []
 | ||
|           this.uploadQueues.splice(index, 1)
 | ||
|         })
 | ||
|     },
 | ||
|     // 当选择项发生变化时收集待上传文件数据
 | ||
|     handleSelectionChange(selection) {
 | ||
|       selection.sort((n1, n2) => {
 | ||
|         return n1.studyIndex - n2.studyIndex
 | ||
|       })
 | ||
|       this.selectArr = selection
 | ||
|     },
 | ||
|     // 根据是否上传状态决定CheckBox 是否可以勾选
 | ||
|     handleSelectable(row) {
 | ||
|       if (row.uploadState.selected) {
 | ||
|         return false
 | ||
|       } else {
 | ||
|         return true
 | ||
|       }
 | ||
|     },
 | ||
|     // 收集已上传文件列表勾选项
 | ||
|     handleUploadedSelectionChange(selection) {
 | ||
|       this.deleteArr = []
 | ||
|       selection.forEach(item => {
 | ||
|         this.deleteArr.push(item.StudyId)
 | ||
|       })
 | ||
|     },
 | ||
|     // 批量删除已上传的影像
 | ||
|     handleBatchDelete() {
 | ||
|       this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
 | ||
|         type: 'warning',
 | ||
|         distinguishCancelAndClose: true
 | ||
|       })
 | ||
|         .then(() => {
 | ||
|           this.studyLoading = true
 | ||
|           deleteStudyList(this.trialId, this.subjectVisitId, this.deleteArr)
 | ||
|             .then(res => {
 | ||
|               if (res.IsSuccess) {
 | ||
|                 this.getStudyInfo()
 | ||
|                 this.$emit('getList')
 | ||
|                 this.$message.success(this.$t('trials:uploadedDicoms:message:deleteSuccessfully'))
 | ||
|               }
 | ||
|             }).catch(() => {
 | ||
|               this.studyLoading = true
 | ||
|             })
 | ||
|         }).catch(() => {})
 | ||
|     },
 | ||
|     // 删除已上传的某个检查
 | ||
|     handleDeleteStudy(row) {
 | ||
|       this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
 | ||
|         type: 'warning',
 | ||
|         distinguishCancelAndClose: true
 | ||
|       })
 | ||
|         .then(() => {
 | ||
|           this.studyLoading = true
 | ||
|           deleteStudyList(this.trialId, this.subjectVisitId, [row.StudyId])
 | ||
|             .then(res => {
 | ||
|               if (res.IsSuccess) {
 | ||
|                 this.getStudyInfo()
 | ||
|                 this.$emit('getList')
 | ||
|                 this.$message.success(this.$t('trials:uploadedDicoms:message:deleteSuccessfully'))
 | ||
|               }
 | ||
|             }).catch(() => {
 | ||
|               this.studyLoading = true
 | ||
|             })
 | ||
|         }).catch(() => {})
 | ||
|     },
 | ||
|     // cancel按钮回调
 | ||
|     cancel() {
 | ||
|       this.scanState = 'cancelling'
 | ||
|       // 关闭上传模态框
 | ||
|       this.$emit('close')
 | ||
|     },
 | ||
|     compare(start, end) {
 | ||
|       start = new Date(start)
 | ||
|       start = start.getTime()
 | ||
|       end = new Date(end)
 | ||
|       end = end.getTime()
 | ||
|       var time = 0
 | ||
|       if (start > end) {
 | ||
|         time = start - end
 | ||
|       } else {
 | ||
|         time = end - start
 | ||
|       }
 | ||
|       return Math.floor(time / 86400000)
 | ||
|     },
 | ||
|     exportFailedFiles(errorFiles) {
 | ||
|       var elementA = document.createElement('a')
 | ||
|       var str = ''
 | ||
|       errorFiles.forEach((el) => {
 | ||
|         str += el + '\n'
 | ||
|       })
 | ||
|       elementA.setAttribute('href', 'data:text/html;charset=utf-8,' + str)
 | ||
|       elementA.setAttribute('download', +new Date() + '.txt')
 | ||
|       elementA.style.display = 'none'
 | ||
|       document.body.appendChild(elementA)
 | ||
|       elementA.click()
 | ||
|       document.body.removeChild(elementA)
 | ||
|     },
 | ||
|     // 设置已删除序列行样式
 | ||
|     tableRowClassName({ row, rowIndex }) {
 | ||
|       if (row.IsDeleted) {
 | ||
|         return 'delete-row'
 | ||
|       } else {
 | ||
|         return ''
 | ||
|       }
 | ||
|     },
 | ||
|     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())
 | ||
|       })
 | ||
|       return newArr.join(' | ')
 | ||
|     }
 | ||
|   }
 | ||
| }
 | ||
| </script>
 | ||
| <style lang="scss">
 | ||
| .upload-dicom-files-wrapper{
 | ||
|   .dicomFiles-table{
 | ||
|     .el-table__body-wrapper{
 | ||
|       height: 300px;
 | ||
|       overflow-y: auto;
 | ||
|     }
 | ||
|   }
 | ||
|   .delete-row{
 | ||
|       text-decoration-line: line-through;
 | ||
|       color: #c0c4cc;
 | ||
|     }
 | ||
|   .previewActive:hover {
 | ||
|     cursor: pointer;
 | ||
|     color: #33dac1;
 | ||
|   }
 | ||
|   #inputForm label {
 | ||
|     font-weight: normal;
 | ||
|   }
 | ||
|   #inputForm .file-input {
 | ||
|     position: relative;
 | ||
|     overflow: hidden;
 | ||
|     display: inline-block;
 | ||
|   }
 | ||
|   #inputForm .file-input input[type='file'] {
 | ||
|     position: absolute;
 | ||
|     top: 0;
 | ||
|     left: 0;
 | ||
|     width: 100%;
 | ||
|     height: 100%;
 | ||
|     opacity: 0;
 | ||
|     cursor: pointer;
 | ||
|   }
 | ||
| 
 | ||
|   #inputForm #listWrapper {
 | ||
|     margin-top: 10px;
 | ||
|     margin-bottom: 50px;
 | ||
|   }
 | ||
| 
 | ||
|   #inputForm #listWrapper a {
 | ||
|     text-decoration: none;
 | ||
|   }
 | ||
|   #inputForm .text-left {
 | ||
|     text-align: left;
 | ||
|   }
 | ||
|   .colorOfRed{
 | ||
|     color:#f44336;
 | ||
|   }
 | ||
| }
 | ||
| 
 | ||
| </style>
 |