下载优化
continuous-integration/drone/push Build is passing Details

main
wangxiaoshuang 2025-12-18 09:51:23 +08:00
parent b024b186b7
commit 6acadf6287
5 changed files with 355 additions and 256 deletions

View File

@ -3671,4 +3671,13 @@ export function visitImageBack(data) {
method: 'put', method: 'put',
data data
}) })
}
// 阅片任务退回
export function VisitImageDownload(data) {
return requestDownload({
url: `/download/VisitImageDownload`,
method: 'post',
responseType: 'blob',
data
})
} }

View File

@ -218,7 +218,8 @@
:close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose"> :close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
<div v-if="downloadType == 'downLoad' || downloadType == 'start'"> <div v-if="downloadType == 'downLoad' || downloadType == 'start'">
<span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span> <span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span>
<el-progress :percentage="percentage * 1"></el-progress> <span>{{ speed }}</span>
<el-progress :percentage="percentage * 1" v-if="downloadVisible"></el-progress>
</div> </div>
<div v-else> <div v-else>
<span>{{ $t('dialog:sattus:ziping') }}</span> <span>{{ $t('dialog:sattus:ziping') }}</span>
@ -304,7 +305,8 @@ export default {
downloadVisible: false, downloadVisible: false,
downloadType: '', downloadType: '',
percentage: 0, percentage: 0,
downLoadImageCount: 0 downLoadImageCount: 0,
speed: '0KB/s'
} }
}, },
created() { created() {
@ -319,6 +321,8 @@ export default {
this.percentage = 0 this.percentage = 0
this.downLoadImageCount = 0 this.downLoadImageCount = 0
this.downloadVisible = false this.downloadVisible = false
this.speed = '0KB/s'
this.downloadId = null
done() done()
}, },
generate() { generate() {
@ -604,6 +608,7 @@ export default {
this.percentage = 0 this.percentage = 0
this.downLoadImageCount = 0 this.downLoadImageCount = 0
this.downloadVisible = false this.downloadVisible = false
this.speed = '0KB/s'
} }
// if (type === 'downLoaded') { // if (type === 'downLoaded') {
// } // }
@ -628,6 +633,7 @@ export default {
connection.start() connection.start()
connection.on("ReceivProgressAsync", (id, obj) => { connection.on("ReceivProgressAsync", (id, obj) => {
console.log(obj) console.log(obj)
this.speed = obj.speed
this.onUploadProgress(id, obj.sizePercent, 'downLoad') this.onUploadProgress(id, obj.sizePercent, 'downLoad')
}); });
} }

View File

@ -5,79 +5,38 @@
<el-form :inline="true"> <el-form :inline="true">
<!-- 受试者编号 --> <!-- 受试者编号 -->
<el-form-item :label="$t('trials:uploadMonitor:table:subjectId')"> <el-form-item :label="$t('trials:uploadMonitor:table:subjectId')">
<el-input <el-input v-model="searchData.SubjectCode" clearable style="width: 140px" />
v-model="searchData.SubjectCode"
clearable
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!-- 患者编号 --> <!-- 患者编号 -->
<el-form-item :label="$t('trials:uploadDicomList:table:pId')"> <el-form-item :label="$t('trials:uploadDicomList:table:pId')">
<el-input <el-input v-model="searchData.PatientIdStr" clearable style="width: 140px" />
v-model="searchData.PatientIdStr"
clearable
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!-- 患者姓名 --> <!-- 患者姓名 -->
<el-form-item :label="$t('trials:uploadDicomList:table:patientName')"> <el-form-item :label="$t('trials:uploadDicomList:table:patientName')">
<el-input <el-input v-model="searchData.PatientName" clearable style="width: 140px" />
v-model="searchData.PatientName"
clearable
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!-- 患者性别 --> <!-- 患者性别 -->
<el-form-item :label="$t('trials:subject:table:gender')"> <el-form-item :label="$t('trials:subject:table:gender')">
<el-select <el-select v-model="searchData.SubjectSex" clearable filterable style="width: 150px">
v-model="searchData.SubjectSex" <el-option v-for="item of $d.Sex" :key="item.id" :label="item.label" :value="item.value" />
clearable
filterable
style="width: 150px"
>
<el-option
v-for="item of $d.Sex"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 访视名称 --> <!-- 访视名称 -->
<el-form-item :label="$t('trials:uploadMonitor:table:visitName')"> <el-form-item :label="$t('trials:uploadMonitor:table:visitName')">
<el-input <el-input v-model="searchData.VisitName" clearable style="width: 140px" />
v-model="searchData.VisitName"
clearable
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!--拍片日期--> <!--拍片日期-->
<el-form-item :label="$t('trials:trials-panel:table:ScanDate')"> <el-form-item :label="$t('trials:trials-panel:table:ScanDate')">
<el-date-picker <el-date-picker v-model="dateValue" type="datetimerange" range-separator="-"
v-model="dateValue"
type="datetimerange"
range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')" :start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :end-placeholder="$t('trials:uploadClinicalData:table:endDate')" clearable
clearable :default-time="['00:00:00', '23:59:59']">
:default-time="['00:00:00', '23:59:59']"
>
</el-date-picker> </el-date-picker>
</el-form-item> </el-form-item>
<!--状态--> <!--状态-->
<el-form-item :label="$t('trials:trials-list:table:status')"> <el-form-item :label="$t('trials:trials-list:table:status')">
<el-select <el-select v-model="searchData.SubmitState" clearable filterable style="width: 150px">
v-model="searchData.SubmitState" <el-option v-for="item of $d.SubmitState" :key="item.id" :label="item.label" :value="item.value" />
clearable
filterable
style="width: 150px"
>
<el-option
v-for="item of $d.SubmitState"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -86,60 +45,39 @@
{{ $t('common:button:search') }} {{ $t('common:button:search') }}
</el-button> </el-button>
<!-- 重置 --> <!-- 重置 -->
<el-button <el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }} {{ $t('common:button:reset') }}
</el-button> </el-button>
<!-- 下载影像 -->
<el-button type="primary" @click="getDownloadSubjectVisitStudyInfo(multipleSelection)"
:disabled="multipleSelection.length <= 0" v-hasPermi="['trials:trials-panel:hirVisit:download']">
{{ $t('trials:inspection:button:downloadImage') }}
</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
<!-- 访视列表:default-sort="{ prop: 'SubmitTime', order: 'descending' }" --> <!-- 访视列表:default-sort="{ prop: 'SubmitTime', order: 'descending' }" -->
<template slot="main-container"> <template slot="main-container">
<el-table <el-table ref="visitList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100"
ref="visitList" @sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
v-loading="loading" <el-table-column type="selection" width="55" v-if="hasPermi(['trials:trials-panel:hirVisit:download'])" />
v-adaptive="{ bottomOffset: 60 }"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
>
<el-table-column min-width="20"> <el-table-column min-width="20">
<template slot-scope="scope"> <template slot-scope="scope">
<i <i v-if="
v-if=" Number(scope.row.SubmitState) === 1 &&
Number(scope.row.SubmitState) === 1 && scope.row.VisitLatestStudyTime
scope.row.VisitLatestStudyTime " class="el-icon-warning-outline" :title="$t('trials:hirVisit:tipMessage:tipOne')" style="color: red"></i>
"
class="el-icon-warning-outline"
:title="$t('trials:hirVisit:tipMessage:tipOne')"
style="color: red"
></i>
</template> </template>
</el-table-column> </el-table-column>
<!-- 受试者编号 --> <!-- 受试者编号 -->
<el-table-column <el-table-column prop="SubjectCode" :label="$t('trials:uploadMonitor:table:subjectId')" show-overflow-tooltip
prop="SubjectCode" sortable="custom" min-width="120" />
:label="$t('trials:uploadMonitor:table:subjectId')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<!-- 患者编号 --> <!-- 患者编号 -->
<el-table-column <el-table-column prop="PatientList.PatientIdStr" :label="$t('trials:uploadDicomList:table:pId')"
prop="PatientList.PatientIdStr" show-overflow-tooltip>
:label="$t('trials:uploadDicomList:table:pId')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<span <span v-for="(item, index) in scope.row.PatientList" :key="`${index}${item.PatientId}`">
v-for="(item, index) in scope.row.PatientList"
:key="`${index}${item.PatientId}`"
>
{{ {{
index === scope.row.PatientList.length - 1 index === scope.row.PatientList.length - 1
? item.PatientIdStr ? item.PatientIdStr
@ -149,32 +87,18 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 患者姓名 --> <!-- 患者姓名 -->
<el-table-column <el-table-column prop="SubjectShortName" :label="$t('trials:researchStaff:table:Name')" show-overflow-tooltip
prop="SubjectShortName" sortable="custom" min-width="100" />
:label="$t('trials:researchStaff:table:Name')"
show-overflow-tooltip
sortable="custom"
min-width="100"
/>
<!-- 性别 --> <!-- 性别 -->
<el-table-column <el-table-column prop="SubjectSex" :label="$t('trials:subject:table:gender')" show-overflow-tooltip
prop="SubjectSex" sortable="custom">
:label="$t('trials:subject:table:gender')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ $fd('Sex', scope.row.SubjectSex) }}</span> <span>{{ $fd('Sex', scope.row.SubjectSex) }}</span>
</template> </template>
</el-table-column> </el-table-column>
<!-- 访视名称 --> <!-- 访视名称 -->
<el-table-column <el-table-column prop="VisitName" :label="$t('trials:uploadMonitor:table:visitName')" show-overflow-tooltip
prop="VisitName" sortable="custom" min-width="100">
:label="$t('trials:uploadMonitor:table:visitName')"
show-overflow-tooltip
sortable="custom"
min-width="100"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="handleOpenStudyDialog(scope.row)"> <el-button type="text" @click="handleOpenStudyDialog(scope.row)">
<span>{{ scope.row.VisitName }}</span> <span>{{ scope.row.VisitName }}</span>
@ -182,39 +106,21 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 最早拍片日期 --> <!-- 最早拍片日期 -->
<el-table-column <el-table-column prop="VisitEarliestStudyTime" :label="$t('trials:trials-panel:table:EarliestScanDate')"
prop="VisitEarliestStudyTime" show-overflow-tooltip sortable="custom" min-width="140" />
:label="$t('trials:trials-panel:table:EarliestScanDate')"
show-overflow-tooltip
sortable="custom"
min-width="140"
/>
<!-- 最晚拍片日期 --> <!-- 最晚拍片日期 -->
<el-table-column <el-table-column prop="VisitLatestStudyTime" :label="$t('trials:linkedRP:table:latestScanDate')"
prop="VisitLatestStudyTime" show-overflow-tooltip sortable="custom" min-width="120" />
:label="$t('trials:linkedRP:table:latestScanDate')"
show-overflow-tooltip
sortable="custom"
min-width="120"
/>
<!-- 状态 --> <!-- 状态 -->
<el-table-column <el-table-column prop="SubmitState" :label="$t('trials:trials-list:table:status')" show-overflow-tooltip
prop="SubmitState" sortable="custom">
:label="$t('trials:trials-list:table:status')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag <el-tag :type="Number(scope.row.SubmitState) === 0
:type=" ? 'warning'
Number(scope.row.SubmitState) === 0 : Number(scope.row.SubmitState) === 1
? 'warning' ? 'danger'
: Number(scope.row.SubmitState) === 1 : ''
? 'danger' ">{{ $fd('SubmitState', Number(scope.row.SubmitState)) }}</el-tag>
: ''
"
>{{ $fd('SubmitState', Number(scope.row.SubmitState)) }}</el-tag
>
</template> </template>
</el-table-column> </el-table-column>
<!-- 打包状态 --> <!-- 打包状态 -->
@ -240,94 +146,57 @@
</template> </template>
</el-table-column> --> </el-table-column> -->
<!-- 提交时间 --> <!-- 提交时间 -->
<el-table-column <el-table-column prop="SubmitTime" :label="$t('trials:crcUpload:table:submitTime')" show-overflow-tooltip
prop="SubmitTime" min-width="100" sortable="custom" />
:label="$t('trials:crcUpload:table:submitTime')"
show-overflow-tooltip
min-width="100"
sortable="custom"
/>
<!--操作--> <!--操作-->
<el-table-column <el-table-column :label="$t('common:action:action')" min-width="200" fixed="right" v-if="
:label="$t('common:action:action')" hasPermi([
min-width="200" 'trials:trials-panel:hirVisit:edit',
fixed="right" 'trials:trials-panel:hirVisit:submit',
v-if=" 'trials:trials-panel:hirVisit:remove',
hasPermi([ 'trials:trials-panel:hirVisit:download',
'trials:trials-panel:hirVisit:edit', ])
'trials:trials-panel:hirVisit:submit', ">
'trials:trials-panel:hirVisit:remove',
'trials:trials-panel:hirVisit:download',
])
"
>
<template slot-scope="scope"> <template slot-scope="scope">
<!--修改检查--> <!--修改检查-->
<el-button <el-button circle icon="el-icon-edit-outline" v-hasPermi="['trials:trials-panel:hirVisit:edit']"
circle :title="$t('trials:hirVisit:button:editStudy')" :disabled="Number(scope.row.SubmitState) > 1"
icon="el-icon-edit-outline" @click.stop="editStudy(scope.row)" />
v-hasPermi="['trials:trials-panel:hirVisit:edit']"
:title="$t('trials:hirVisit:button:editStudy')"
:disabled="Number(scope.row.SubmitState) > 1"
@click.stop="editStudy(scope.row)"
/>
<!--提交--> <!--提交-->
<el-button <el-button circle icon="el-icon-position" v-hasPermi="['trials:trials-panel:hirVisit:submit']" :disabled="Number(scope.row.SubmitState) != 1 ||
circle !scope.row.VisitLatestStudyTime
icon="el-icon-position" " :title="$t('common:button:submit')" @click.stop="submit(scope.row)" />
v-hasPermi="['trials:trials-panel:hirVisit:submit']"
:disabled="
Number(scope.row.SubmitState) != 1 ||
!scope.row.VisitLatestStudyTime
"
:title="$t('common:button:submit')"
@click.stop="submit(scope.row)"
/>
<!--删除--> <!--删除-->
<el-button <el-button circle icon="el-icon-delete" v-hasPermi="['trials:trials-panel:hirVisit:remove']"
circle @click.stop="remove(scope.row)" :disabled="Number(scope.row.SubmitState) > 1"
icon="el-icon-delete" :title="$t('common:button:delete')" />
v-hasPermi="['trials:trials-panel:hirVisit:remove']"
@click.stop="remove(scope.row)"
:disabled="Number(scope.row.SubmitState) > 1"
:title="$t('common:button:delete')"
/>
<!--下载报告--> <!--下载报告-->
<el-button <el-button v-hasPermi="['trials:trials-panel:hirVisit:download']" circle :loading="downloading"
v-hasPermi="['trials:trials-panel:hirVisit:download']" icon="el-icon-download" :disabled="Number(scope.row.SubmitState) !== 2"
circle :title="$t('trials:reading:button:download')" @click="getDownloadSubjectVisitStudyInfo([scope.row])" />
:loading="downloading"
icon="el-icon-download"
:disabled="Number(scope.row.SubmitState) !== 2"
:title="$t('trials:reading:button:download')"
@click="getDownloadSubjectVisitStudyInfo(scope.row)"
/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页组件 --> <!-- 分页组件 -->
<pagination <pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
class="page" @pagination="getList" />
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
</template> </template>
<!--修改检查--> <!--修改检查-->
<editStudyList <editStudyList :visible.sync="editStudyVisible" :data="editStudyData" v-if="editStudyVisible" @getList="getList" />
:visible.sync="editStudyVisible"
:data="editStudyData"
v-if="editStudyVisible"
@getList="getList"
/>
<!--访视详情--> <!--访视详情-->
<visitInfo <visitInfo v-if="visitVisible" :visible.sync="visitVisible" :rowData="rowData" />
v-if="visitVisible" <el-dialog :title="$t('dialog:title:downLoadProgress')" :visible.sync="downloadVisible" width="35%"
:visible.sync="visitVisible" :close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
:rowData="rowData" <div v-if="downloadType == 'downLoad' || downloadType == 'start'">
/> <span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span>
<span>{{ speed }}</span>
<el-progress :percentage="percentage * 1"></el-progress>
</div>
<div v-else>
<span>{{ $t('dialog:sattus:ziping') }}</span>
</div>
</el-dialog>
</BaseContainer> </BaseContainer>
</template> </template>
<script> <script>
@ -339,8 +208,11 @@ import { deleteSubjectVisit } from '@/api/trials'
import { getPatientSubejctVisitList } from '@/api/trials/visit.js' import { getPatientSubejctVisitList } from '@/api/trials/visit.js'
import { submitVisitStudyBinding } from '@/api/inspection.js' import { submitVisitStudyBinding } from '@/api/inspection.js'
import { downLoadFile } from '@/utils/stream.js' import { downLoadFile } from '@/utils/stream.js'
import { getToken } from '@/utils/auth'
import * as signalR from '@microsoft/signalr'
import { import {
getDownloadSubjectVisitStudyInfo, getDownloadSubjectVisitStudyInfo,
VisitImageDownload,
downloadImageSuccess, downloadImageSuccess,
} from '@/api/trials.js' } from '@/api/trials.js'
const defaultSearchData = () => { const defaultSearchData = () => {
@ -389,6 +261,12 @@ export default {
// //
downloading: false, downloading: false,
downloadId: null, downloadId: null,
downloadVisible: false,
downloadType: '',
percentage: 0,
downLoadImageCount: 0,
speed: '0KB/s',
multipleSelection: []
} }
}, },
created() { created() {
@ -398,7 +276,56 @@ export default {
} }
this.getList() this.getList()
}, },
mounted() {
let connection = new signalR.HubConnectionBuilder()
.withUrl("/DownloadHub", { accessTokenFactory: () => getToken() })
.configureLogging(signalR.LogLevel.Information)
.withAutomaticReconnect()
.build()
connection.start()
connection.on("ReceivProgressAsync", (id, obj) => {
console.log(obj)
this.speed = obj.speed
this.onUploadProgress(id, obj.sizePercent, 'downLoad')
});
},
methods: { methods: {
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleClose(done) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
this.downloadId = null
done()
},
generate() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
async onUploadProgress(id, num, type = 'start') {
if (id !== this.downloadId) return false
this.downloadType = type
if (type === 'start') {
this.downloadVisible = true
}
if (type === 'downLoad') {
this.percentage = num
}
if (num >= 100) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
}
},
// //
handleSearch() { handleSearch() {
this.getList() this.getList()
@ -517,20 +444,24 @@ export default {
} }
}, },
// //
async getDownloadSubjectVisitStudyInfo(row) { async getDownloadSubjectVisitStudyInfo(arr) {
if (this.downloading) return if (this.downloading) return
try { try {
let data = { let data = {
SubjectVisitId: row.SubjectVisitId, // SubjectVisitId: row.SourceSubjectVisitId,
SubjectVisitIdList: arr.map(item => item.SourceSubjectVisitId),
TrialId: this.$route.query.trialId, TrialId: this.$route.query.trialId,
} }
this.downloading = true this.downloadId = this.generate()
let res = await getDownloadSubjectVisitStudyInfo(data) data.CurrentNoticeId = this.downloadId
this.downloading = false this.onUploadProgress(this.downloadId)
if (res.IsSuccess) { // this.downloading = true
this.downloadId = res.OtherInfo await VisitImageDownload(data)
this.downloadImage(res.Result) // this.downloading = false
} // if (res.IsSuccess) {
// this.downloadId = res.OtherInfo
// this.downloadImage(res.Result)
// }
} catch (err) { } catch (err) {
this.downloading = false this.downloading = false
console.log(err) console.log(err)
@ -564,11 +495,9 @@ export default {
series.InstanceList.forEach((instance) => { series.InstanceList.forEach((instance) => {
let fileName = instance.Path.split('/').pop() let fileName = instance.Path.split('/').pop()
let obj = { let obj = {
name: `${data.SubjectCode}_${data.VisitName}/${ name: `${data.SubjectCode}_${data.VisitName}/${study.StudyCode
study.StudyCode }_${study.StudyTime.split(' ')[0]}_${series.Modality
}_${study.StudyTime.split(' ')[0]}_${ }/${fileName}`,
series.Modality
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path, url: this.OSSclientConfig.basePath + instance.Path,
} }
files.push(obj) files.push(obj)

View File

@ -79,12 +79,18 @@
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset"> <el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }} {{ $t('common:button:reset') }}
</el-button> </el-button>
<!-- 下载影像 -->
<el-button type="primary" @click="getDownloadSubjectVisitStudyInfo(multipleSelection)"
v-hasPermi="['trials:readTask:report']" :disabled="multipleSelection.length <= 0">
{{ $t('trials:inspection:button:downloadImage') }}
</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<div slot="main-container"> <div slot="main-container">
<el-table v-adaptive="{ bottomOffset: 75 }" :data="list" stripe height="100" <el-table v-adaptive="{ bottomOffset: 75 }" :data="list" stripe height="100" @sort-change="handleSortChange"
@sort-change="handleSortChange"> @selection-change="handleSelectionChange">
<el-table-column type="selection" width="55" v-if="hasPermi(['trials:readTask:report'])" />
<!-- 受试者编号 --> <!-- 受试者编号 -->
<el-table-column prop="SubjectCode" min-width="100" :label="$t('trials:reviewTrack:table:subjectCode')" <el-table-column prop="SubjectCode" min-width="100" :label="$t('trials:reviewTrack:table:subjectCode')"
show-overflow-tooltip sortable="custom" /> show-overflow-tooltip sortable="custom" />
@ -240,7 +246,7 @@
:loading="downloading" :title="$t('trials:reading:button:uploadImages')" @click=" :loading="downloading" :title="$t('trials:reading:button:uploadImages')" @click="
handleCommand( handleCommand(
'getDownloadSubjectVisitStudyInfo', 'getDownloadSubjectVisitStudyInfo',
scope.row [scope.row]
) )
" /> " />
</template> </template>
@ -431,6 +437,17 @@
width="600px"> width="600px">
<ChatForm :row-data="currentRow" @getList="getList" @close="auditRecordVisible = false" /> <ChatForm :row-data="currentRow" @getList="getList" @close="auditRecordVisible = false" />
</el-dialog> </el-dialog>
<el-dialog :title="$t('dialog:title:downLoadProgress')" :visible.sync="downloadVisible" width="35%"
:close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
<div v-if="downloadType == 'downLoad' || downloadType == 'start'">
<span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span>
<span>{{ speed }}</span>
<el-progress :percentage="percentage * 1"></el-progress>
</div>
<div v-else>
<span>{{ $t('dialog:sattus:ziping') }}</span>
</div>
</el-dialog>
</BaseContainer> </BaseContainer>
</template> </template>
<script> <script>
@ -445,11 +462,13 @@ import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination' import Pagination from '@/components/Pagination'
import ChatForm from './components/ChatForm' import ChatForm from './components/ChatForm'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import * as signalR from '@microsoft/signalr'
import { showReadReport, showTumorReport } from '@/api/export' import { showReadReport, showTumorReport } from '@/api/export'
import { downLoadFile } from '@/utils/stream.js' import { downLoadFile } from '@/utils/stream.js'
import { getAutoCutNextTask } from '@/api/user' import { getAutoCutNextTask } from '@/api/user'
import { import {
getDownloadSubjectVisitStudyInfo, getDownloadSubjectVisitStudyInfo,
VisitImageDownload,
downloadImageSuccess, downloadImageSuccess,
} from '@/api/trials.js' } from '@/api/trials.js'
import { openWindow } from "@/utils/splitScreen"; import { openWindow } from "@/utils/splitScreen";
@ -521,6 +540,12 @@ export default {
// //
downloading: false, downloading: false,
downloadId: null, downloadId: null,
downloadVisible: false,
downloadType: '',
percentage: 0,
downLoadImageCount: 0,
speed: '0KB/s',
multipleSelection: []
} }
}, },
watch: { watch: {
@ -538,6 +563,17 @@ export default {
mounted() { mounted() {
this.trialId = this.$route.query.trialId this.trialId = this.$route.query.trialId
this.getTrialCriterionList() this.getTrialCriterionList()
let connection = new signalR.HubConnectionBuilder()
.withUrl("/DownloadHub", { accessTokenFactory: () => getToken() })
.configureLogging(signalR.LogLevel.Information)
.withAutomaticReconnect()
.build()
connection.start()
connection.on("ReceivProgressAsync", (id, obj) => {
console.log(obj)
this.speed = obj.speed
this.onUploadProgress(id, obj.sizePercent, 'downLoad')
});
}, },
beforeDestroy() { beforeDestroy() {
if (this.openWindow) { if (this.openWindow) {
@ -545,6 +581,42 @@ export default {
} }
}, },
methods: { methods: {
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleClose(done) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.downloadId = null
this.speed = '0KB/s'
done()
},
generate() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
async onUploadProgress(id, num, type = 'start') {
if (id !== this.downloadId) return false
this.downloadType = type
if (type === 'start') {
this.downloadVisible = true
}
if (type === 'downLoad') {
this.percentage = num
}
if (num >= 100) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
}
},
// //
handleCommand(command, item, key) { handleCommand(command, item, key) {
this[command](item, key) this[command](item, key)
@ -588,20 +660,24 @@ export default {
} }
}, },
// //
async getDownloadSubjectVisitStudyInfo(row) { async getDownloadSubjectVisitStudyInfo(arr) {
if (this.downloading) return if (this.downloading) return
try { try {
let data = { let data = {
SubjectVisitId: row.SourceSubjectVisitId, // SubjectVisitId: row.SourceSubjectVisitId,
SubjectVisitIdList: arr.map(item => item.SourceSubjectVisitId),
TrialId: this.$route.query.trialId, TrialId: this.$route.query.trialId,
} }
this.downloading = true this.downloadId = this.generate()
let res = await getDownloadSubjectVisitStudyInfo(data) data.CurrentNoticeId = this.downloadId
this.downloading = false this.onUploadProgress(this.downloadId)
if (res.IsSuccess) { // this.downloading = true
this.downloadId = res.OtherInfo await VisitImageDownload(data)
this.downloadImage(res.Result) // this.downloading = false
} // if (res.IsSuccess) {
// this.downloadId = res.OtherInfo
// this.downloadImage(res.Result)
// }
} catch (err) { } catch (err) {
this.downloading = false this.downloading = false
console.log(err) console.log(err)

View File

@ -61,6 +61,11 @@
<el-button type="primary" icon="el-icon-download" @click="handleExport"> <el-button type="primary" icon="el-icon-download" @click="handleExport">
{{ $t('common:button:export') }} {{ $t('common:button:export') }}
</el-button> </el-button>
<!-- 下载影像 -->
<el-button type="primary" @click="getDownloadSubjectVisitStudyInfo(multipleSelection)"
:disabled="multipleSelection.length <= 0">
{{ $t('trials:inspection:button:downloadImage') }}
</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
</template> </template>
@ -69,8 +74,9 @@
<template slot="main-container"> <template slot="main-container">
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100" <el-table v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100"
@sort-change="handleSortByColumn" ref="redManagenentTable" @sort-change="handleSortByColumn" ref="redManagenentTable"
:default-sort="{ prop: 'CreateTime', order: 'descending' }"> :default-sort="{ prop: 'CreateTime', order: 'descending' }" @selection-change="handleSelectionChange">
<el-table-column type="index" width="40" /> <el-table-column type="selection" width="55" />
<!-- <el-table-column type="index" width="40" /> -->
<!-- 受试者编号 --> <!-- 受试者编号 -->
<el-table-column prop="SubjectCode" :label="$t('trials:uploadMonitor:table:subjectId')" show-overflow-tooltip <el-table-column prop="SubjectCode" :label="$t('trials:uploadMonitor:table:subjectId')" show-overflow-tooltip
sortable="custom" /> sortable="custom" />
@ -171,7 +177,7 @@
<!--下载影像--> <!--下载影像-->
<el-button circle icon="el-icon-download" :loading="downloading" <el-button circle icon="el-icon-download" :loading="downloading"
:title="$t('trials:reading:button:uploadImages')" @click=" :title="$t('trials:reading:button:uploadImages')" @click="
handleCommand('getDownloadSubjectVisitStudyInfo', scope.row) handleCommand('getDownloadSubjectVisitStudyInfo', [scope.row])
" /> " />
<!--退回--> <!--退回-->
<el-button circle icon="el-icon-back" :disabled="![0, 5].includes(scope.row.TaskState)" <el-button circle icon="el-icon-back" :disabled="![0, 5].includes(scope.row.TaskState)"
@ -218,6 +224,17 @@
</template> </template>
</base-model> </base-model>
</template> </template>
<el-dialog :title="$t('dialog:title:downLoadProgress')" :visible.sync="downloadVisible" width="35%"
:close-on-click-modal="false" :close-on-press-escape="false" :before-close="handleClose">
<div v-if="downloadType == 'downLoad' || downloadType == 'start'">
<span style="margin-bottom: 5px;">{{ $t('dialog:sattus:downLoading') }}</span>
<span>{{ speed }}</span>
<el-progress :percentage="percentage * 1"></el-progress>
</div>
<div v-else>
<span>{{ $t('dialog:sattus:ziping') }}</span>
</div>
</el-dialog>
</BaseContainer> </BaseContainer>
</template> </template>
<script> <script>
@ -226,6 +243,7 @@ import Pagination from '@/components/Pagination'
import exportList from './components/exportList.vue' import exportList from './components/exportList.vue'
import { getPatientVisitTaskList } from '@/api/readManagenent.js' import { getPatientVisitTaskList } from '@/api/readManagenent.js'
import { getToken } from '@/utils/auth' import { getToken } from '@/utils/auth'
import * as signalR from '@microsoft/signalr'
// import { getSystemConfirmedCreiterionList } from "@/api/trials"; // import { getSystemConfirmedCreiterionList } from "@/api/trials";
import { getTrialCriterionList } from '@/api/trials/reading' import { getTrialCriterionList } from '@/api/trials/reading'
import { showReadReport, showTumorReport } from '@/api/export' import { showReadReport, showTumorReport } from '@/api/export'
@ -233,6 +251,7 @@ import { downLoadFile } from '@/utils/stream.js'
import { createImageShare, updateImageShare } from '@/api/share' import { createImageShare, updateImageShare } from '@/api/share'
import { import {
getDownloadSubjectVisitStudyInfo, getDownloadSubjectVisitStudyInfo,
VisitImageDownload,
downloadImageSuccess, downloadImageSuccess,
visitImageBack visitImageBack
} from '@/api/trials.js' } from '@/api/trials.js'
@ -314,7 +333,14 @@ export default {
shareId: null, shareId: null,
shareLink: null, shareLink: null,
options: [1, 7, 15, 30], options: [1, 7, 15, 30],
OpenImageShare: false OpenImageShare: false,
downloadId: null,
downloadVisible: false,
downloadType: '',
percentage: 0,
downLoadImageCount: 0,
speed: '0KB/s',
multipleSelection: []
} }
}, },
created() { created() {
@ -324,7 +350,56 @@ export default {
this.OpenImageShare = JSON.parse(localStorage.getItem('CompanyInfo')).OpenImageShare this.OpenImageShare = JSON.parse(localStorage.getItem('CompanyInfo')).OpenImageShare
} }
}, },
mounted() {
let connection = new signalR.HubConnectionBuilder()
.withUrl("/DownloadHub", { accessTokenFactory: () => getToken() })
.configureLogging(signalR.LogLevel.Information)
.withAutomaticReconnect()
.build()
connection.start()
connection.on("ReceivProgressAsync", (id, obj) => {
console.log(obj)
this.speed = obj.speed
this.onUploadProgress(id, obj.sizePercent, 'downLoad')
});
},
methods: { methods: {
handleSelectionChange(val) {
this.multipleSelection = val;
},
handleClose(done) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.downloadId = null
this.speed = '0KB/s'
done()
},
generate() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = Math.random() * 16 | 0;
const v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
},
async onUploadProgress(id, num, type = 'start') {
if (id !== this.downloadId) return false
this.downloadType = type
if (type === 'start') {
this.downloadVisible = true
}
if (type === 'downLoad') {
this.percentage = num
}
if (num >= 100) {
this.downLoadType = 'start'
this.percentage = 0
this.downLoadImageCount = 0
this.downloadVisible = false
this.speed = '0KB/s'
}
},
async imageBack(row) { async imageBack(row) {
try { try {
let confirm = await this.$confirm(this.$t('trials:trials-panel:reading:confirm:imageBack'), '', { let confirm = await this.$confirm(this.$t('trials:trials-panel:reading:confirm:imageBack'), '', {
@ -524,20 +599,24 @@ export default {
} }
}, },
// //
async getDownloadSubjectVisitStudyInfo(row) { async getDownloadSubjectVisitStudyInfo(arr) {
if (this.downloading) return if (this.downloading) return
try { try {
let data = { let data = {
SubjectVisitId: row.SourceSubjectVisitId, // SubjectVisitId: row.SourceSubjectVisitId,
SubjectVisitIdList: arr.map(item => item.SourceSubjectVisitId),
TrialId: this.$route.query.trialId, TrialId: this.$route.query.trialId,
} }
this.downloading = true this.downloadId = this.generate()
let res = await getDownloadSubjectVisitStudyInfo(data) data.CurrentNoticeId = this.downloadId
this.downloading = false this.onUploadProgress(this.downloadId)
if (res.IsSuccess) { // this.downloading = true
this.downloadId = res.OtherInfo await VisitImageDownload(data)
this.downloadImage(res.Result) // this.downloading = false
} // if (res.IsSuccess) {
// this.downloadId = res.OtherInfo
// this.downloadImage(res.Result)
// }
} catch (err) { } catch (err) {
this.downloading = false this.downloading = false
console.log(err) console.log(err)