409 lines
20 KiB
Vue
409 lines
20 KiB
Vue
<template>
|
|
<BaseContainer class="image-summary-wrapper">
|
|
<template slot="search-container">
|
|
<el-form :inline="true">
|
|
<!-- 中心 -->
|
|
<el-form-item :label="$t('trials:imageSummary:table:siteNo')">
|
|
<el-select v-model="searchData.TrialSiteId" clearable filterable>
|
|
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteCode"
|
|
:value="item.TrialSiteId" />
|
|
</el-select>
|
|
</el-form-item>
|
|
<!-- 受试者 -->
|
|
<el-form-item :label="$t('trials:imageSummary:table:subject')">
|
|
<el-input v-model="searchData.SubjectCode" />
|
|
</el-form-item>
|
|
<!-- 拍片时间 -->
|
|
<el-form-item :label="$t('trials:imageSummary:table:operateTime')">
|
|
<el-date-picker v-model="timeList" @change="changeTimeList" value-format="yyyy-MM-dd HH:mm:ss"
|
|
:default-time="['00:00:00', '23:59:59']" type="datetimerange">
|
|
</el-date-picker>
|
|
</el-form-item>
|
|
<el-form-item>
|
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
|
{{ $t('common:button:search') }}
|
|
</el-button>
|
|
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
|
{{ $t('common:button:reset') }}
|
|
</el-button>
|
|
<el-button type="primary" @click="handleExport">
|
|
{{ $t('common:button:export') }}
|
|
</el-button>
|
|
<el-button type="primary" @click="handleExportImage(false)" :disabled="selectArr.length <= 0"
|
|
v-if="hasPermi(['trials:trials-panel:trial-summary:image-summary:exportImage'])">
|
|
{{ $t('trials:imageSummary:button:export_dicom') }}
|
|
</el-button>
|
|
<el-button type="primary" @click="handleExportImage(false, true)" :disabled="selectArr.length <= 0"
|
|
v-if="hasPermi(['trials:trials-panel:trial-summary:image-summary:exportImage'])">
|
|
{{ $t('trials:imageSummary:button:export_readingDicom') }}
|
|
</el-button>
|
|
<el-button type="primary" @click="handleExportImage(true)" :disabled="selectArr.length <= 0"
|
|
v-if="hasPermi(['trials:trials-panel:trial-summary:image-summary:exportKeyImage'])">
|
|
{{ $t('trials:imageSummary:button:export_image') }}
|
|
</el-button>
|
|
<el-button type="primary" @click="statistics">
|
|
{{ $t('trials:imageSummary:button:statistics') }}
|
|
</el-button>
|
|
</el-form-item>
|
|
</el-form>
|
|
</template>
|
|
<template slot="main-container">
|
|
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="loading" :data="list" @sort-change="handleSortChange"
|
|
@selection-change="handleSelectionChange" stripe height="100"
|
|
:default-sort="{ prop: 'CreateTime', order: 'descending' }">
|
|
<el-table-column type="selection" width="55" />
|
|
<!-- 中心编号 -->
|
|
<el-table-column prop="TrialSiteCode" min-width="100" :label="$t('trials:imageSummary:table:siteNo')"
|
|
show-overflow-tooltip sortable="custom" />
|
|
<!-- 受试者 -->
|
|
<el-table-column prop="SubjectCode" min-width="100" :label="$t('trials:imageSummary:table:subject')"
|
|
show-overflow-tooltip sortable="custom" />
|
|
<!-- 访视 -->
|
|
<el-table-column prop="VisitName" min-width="120" :label="$t('trials:imageSummary:table:visit')"
|
|
show-overflow-tooltip sortable="custom" />
|
|
<!-- 检查数量 -->
|
|
<el-table-column prop="TotalStudyCount" min-width="120"
|
|
:label="$t('trials:imageSummary:table:TotalStudyCount')" show-overflow-tooltip sortable="custom" />
|
|
<!-- 影像类型 -->
|
|
<el-table-column prop="VisitName" min-width="120" :label="$t('trials:imageSummary:table:imageType')"
|
|
show-overflow-tooltip sortable="custom">
|
|
<template slot-scope="scope">
|
|
<el-tag v-if="scope.row.IsHaveDicom" type="primary">{{
|
|
$fd('IsDicom', true)
|
|
}}</el-tag>
|
|
<el-tag v-if="scope.row.IsHaveNoneDicom" type="primary">{{
|
|
$fd('IsDicom', false)
|
|
}}</el-tag>
|
|
</template>
|
|
</el-table-column>
|
|
<!-- 影像数量 -->
|
|
<el-table-column prop="TotalImageCount" min-width="120"
|
|
:label="$t('trials:imageSummary:table:TotalImageCount')" show-overflow-tooltip sortable="custom" />
|
|
<!-- 影像大小 -->
|
|
<el-table-column prop="TotalImageSizeStr" min-width="120"
|
|
:label="$t('trials:imageSummary:table:TotalImageSizeStr')" show-overflow-tooltip
|
|
sortable="custom" />
|
|
<!-- 阅片影像大小 -->
|
|
<el-table-column prop="TotalReadingImageSizeStr" min-width="120"
|
|
:label="$t('trials:imageSummary:table:TotalReadingImageSizeStr')" show-overflow-tooltip
|
|
sortable="custom" />
|
|
<!-- 最早拍片日期 -->
|
|
<el-table-column prop="EarliestScanDate" min-width="120"
|
|
:label="$t('trials:imageSummary:table:EarliestScanDate')" show-overflow-tooltip sortable="custom" />
|
|
<!-- 最晚拍片日期 -->
|
|
<el-table-column prop="LatestScanDate" min-width="120"
|
|
:label="$t('trials:imageSummary:table:LatestScanDate')" show-overflow-tooltip sortable="custom" />
|
|
<el-table-column prop="" fixed="right" :label="$t('common:action:action')" show-overflow-tooltip
|
|
v-if="hasPermi(['trials:trials-panel:trial-summary:image-summary:toUpload', 'trials:tab:uploadMonitor'])">
|
|
<template slot-scope="scope">
|
|
<!-- 详情 -->
|
|
<el-button icon="el-icon-position" circle @click="toUpload(scope.row)"
|
|
:title="$t('trials:imageSummary:action:toUpload')" />
|
|
</template>
|
|
</el-table-column>
|
|
</el-table>
|
|
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
|
@pagination="getList" />
|
|
<div class="remark">
|
|
<span>{{ $t('trials:imageSummary:remark:TotalImageSizeStr') }}</span>
|
|
<span class="size">{{ image_size.TotalImageSizeStr }}</span>,
|
|
<span>{{ $t('trials:imageSummary:remark:SubjectImageAVGSizeStr') }}</span>
|
|
<span class="size">{{ image_size.SubjectImageAVGSizeStr }} </span>,
|
|
<span>{{ $t('trials:imageSummary:remark:SubjectVisitImageAVGSizeStr') }}</span>
|
|
<span class="size">{{ image_size.SubjectVisitImageAVGSizeStr }}</span><span>{{ `; ` }}</span>
|
|
<span>{{ $t('trials:imageSummary:remark:TotalReadingImageSizeStr') }}</span>
|
|
<span class="size">{{ image_size.TotalReadingImageSizeStr }} </span><span>{{ `; ` }}</span>
|
|
<span>{{ $t('trials:imageSummary:remark:CheckImageSize') }}</span>
|
|
<span class="size">{{ image_size.CheckImageSize }} </span>
|
|
</div>
|
|
</template>
|
|
</BaseContainer>
|
|
</template>
|
|
<script>
|
|
import Pagination from '@/components/Pagination'
|
|
import BaseContainer from '@/components/BaseContainer'
|
|
import { getTrialSiteSelect, getTrialVisitImageStatList, getTrialVisitImageStatInfo, getExportSubjectVisitImageList } from '@/api/trials'
|
|
import { downLoadFile } from '@/utils/stream.js'
|
|
import { getTrialVisitImageStatList_Export } from '@/api/export'
|
|
const searchDataDefault = () => {
|
|
return {
|
|
SortField: '',
|
|
Asc: false,
|
|
PageIndex: 1,
|
|
PageSize: 20,
|
|
TrialSiteId: null,
|
|
SubjectCode: null,
|
|
BeginScanDate: null,
|
|
EndScanDate: null
|
|
}
|
|
}
|
|
export default {
|
|
name: "imageSummary",
|
|
components: { Pagination, BaseContainer },
|
|
data() {
|
|
return {
|
|
total: 0,
|
|
loading: false,
|
|
searchData: searchDataDefault(),
|
|
ResearchProgramNo: null,
|
|
list: [],
|
|
siteOptions: [],
|
|
timeList: [],
|
|
selectArr: [],
|
|
image_size: {
|
|
TotalImageSizeStr: null,
|
|
SubjectImageAVGSizeStr: null,
|
|
SubjectVisitImageAVGSizeStr: null,
|
|
TotalReadingImageSizeStr: null,
|
|
CheckImageSize: null
|
|
}
|
|
}
|
|
},
|
|
created() {
|
|
this.getSite()
|
|
this.getList()
|
|
},
|
|
methods: {
|
|
async getList() {
|
|
try {
|
|
this.searchData.TrialId = this.$route.query.trialId
|
|
this.loading = true
|
|
let res = await getTrialVisitImageStatList(this.searchData)
|
|
this.loading = false
|
|
if (res.IsSuccess) {
|
|
this.list = res.Result.CurrentPageData
|
|
this.total = res.Result.TotalCount
|
|
}
|
|
} catch (err) {
|
|
this.loading = false
|
|
console.log(err)
|
|
}
|
|
},
|
|
// 导出表格
|
|
async handleExport() {
|
|
this.loading = true
|
|
try {
|
|
await getTrialVisitImageStatList_Export(this.searchData)
|
|
this.loading = false
|
|
} catch (e) {
|
|
this.loading = false
|
|
}
|
|
},
|
|
// 导出影像或关键图
|
|
async handleExportImage(IsKeyImage = false, IsExportReading = false) {
|
|
try {
|
|
let data = {
|
|
TrialId: this.$route.query.trialId,
|
|
IsKeyImage,
|
|
IsExportReading
|
|
}
|
|
data.SubjectVisitIdList = this.selectArr.map(item => item.SubjectVisitId)
|
|
if (!IsKeyImage) {
|
|
let confirm = await this.$confirm(this.$t('trials:imageSummary:confirm:space').replace('xxx', this.image_size.CheckImageSize))
|
|
if (!confirm) return false
|
|
}
|
|
let res = await getExportSubjectVisitImageList(data)
|
|
if (res.IsSuccess) {
|
|
this.downLoad(IsKeyImage, res.Result, IsExportReading)
|
|
}
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
},
|
|
// 下载
|
|
async downLoad(IsKeyImage = false, row, IsExportReading = false) {
|
|
try {
|
|
let { files, name } = this.formatDownloadFile(IsKeyImage, row, IsExportReading)
|
|
let res = await downLoadFile(files, name, 'zip')
|
|
// }
|
|
} catch (err) {
|
|
console.log(err)
|
|
}
|
|
},
|
|
// 格式化下载文件路径
|
|
formatDownloadFile(IsKeyImage = false, row, IsExportReading = false) {
|
|
let files = [],
|
|
name = `${this.$route.query.researchProgramNo}_${this.$t('trials:imageSummary:downloadname:dicom')}_${Date.now()}.zip`;
|
|
if (IsExportReading) {
|
|
name = `${this.$route.query.researchProgramNo}_${this.$t('trials:imageSummary:downloadname:readingDicom')}_${Date.now()}.zip`;
|
|
}
|
|
if (!IsKeyImage) {
|
|
//中心ID/受试者ID/访视名/Study ID_Study Date_Modality/文件
|
|
row.VisitList.forEach(visit => {
|
|
if (visit.StudyList && visit.StudyList.length > 0) {
|
|
visit.StudyList.forEach(study => {
|
|
let arr = []
|
|
study.SeriesList.forEach(item => {
|
|
if (!arr.includes(item.Modality)) {
|
|
arr.push(item.Modality)
|
|
}
|
|
})
|
|
let str = arr.join('_')
|
|
let time = study.StudyTime.split(' ')[0]
|
|
if (study.StudyDIRPath && !study.dirHas) {
|
|
study.dirHas = true
|
|
let obj = {
|
|
name: `${visit.TrialSiteCode}/${visit.SubjectCode}/${visit.VisitName}/${study.StudyCode}_${time}_${str}/DICOMDIR`,
|
|
url: this.OSSclientConfig.basePath + study.StudyDIRPath,
|
|
}
|
|
files.push(obj)
|
|
}
|
|
if (study.SeriesList && study.SeriesList.length > 0) {
|
|
study.SeriesList.forEach(serie => {
|
|
|
|
if (serie.InstanceList && serie.InstanceList.length > 0) {
|
|
serie.InstanceList.forEach(instance => {
|
|
let instanceArr = instance.Path.split("/")
|
|
let fileName = instance.FileName || instanceArr[instanceArr.length - 1]
|
|
let obj = {
|
|
name: `${visit.TrialSiteCode}/${visit.SubjectCode}/${visit.VisitName}/${study.StudyCode}_${time}_${str}/IMAGE/${fileName}`,
|
|
url: this.OSSclientConfig.basePath + instance.Path,
|
|
IsEncapsulated: instance.IsEncapsulated
|
|
}
|
|
files.push(obj)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
if (visit.NoneDicomStudyList && visit.NoneDicomStudyList.length > 0) {
|
|
visit.NoneDicomStudyList.forEach(noneDicomStudy => {
|
|
if (noneDicomStudy.FileList && noneDicomStudy.FileList.length > 0) {
|
|
noneDicomStudy.FileList.forEach(file => {
|
|
let time = noneDicomStudy.ImageDate.split(' ')[0]
|
|
let obj = {
|
|
name: `${visit.TrialSiteCode}/${visit.SubjectCode}/${visit.VisitName}/${noneDicomStudy.StudyCode}_${time}_${noneDicomStudy.Modality}/${file.FileName}`,
|
|
url: this.OSSclientConfig.basePath + file.Path,
|
|
}
|
|
files.push(obj)
|
|
})
|
|
}
|
|
})
|
|
}
|
|
})
|
|
} else {
|
|
//项目研究方案号(评估标准)/中心ID/受试者ID/访视名/阅片人角色-裁判选择标记/文件名
|
|
name = `${this.$route.query.researchProgramNo}_${this.$t('trials:imageSummary:downloadname:keyImage')}_${Date.now()}.zip`
|
|
row.forEach(item => {
|
|
['QuestionMarkPictureList', 'TableQuestionRowPictureList', 'ReadingNoneDicomMarkPathList'].forEach(key => {
|
|
if (item[key] && item[key].length > 0) {
|
|
item[key].forEach(data => {
|
|
['PicturePath', 'otherPicturePath'].forEach(imgKey => {
|
|
if (data[imgKey]) {
|
|
let arr = data[imgKey].split("/")
|
|
let fileName = arr[arr.length - 1]
|
|
let obj = {
|
|
name: `${item.CriterionName}/${item.TrialSiteCode}/${item.SubjectCode}/${item.VisitName}/${this.$fd('ArmEnum', item.ArmEnum)}_${this.$fd('IsJudgeSelect', String(item.IsJudgeSelect))}/${fileName}`,
|
|
url: this.OSSclientConfig.basePath + data[imgKey],
|
|
}
|
|
files.push(obj)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
})
|
|
})
|
|
}
|
|
|
|
return { files, name }
|
|
},
|
|
// 获取统计数据
|
|
async statistics() {
|
|
try {
|
|
let params = {
|
|
TrialId: this.$route.query.trialId
|
|
}
|
|
this.loading = true
|
|
let res = await getTrialVisitImageStatInfo(params)
|
|
this.loading = false
|
|
if (res.IsSuccess) {
|
|
this.image_size.TotalImageSizeStr = res.Result.TotalImageSizeStr;
|
|
this.image_size.SubjectImageAVGSizeStr = res.Result.SubjectImageAVGSizeStr;
|
|
this.image_size.SubjectVisitImageAVGSizeStr = res.Result.SubjectVisitImageAVGSizeStr;
|
|
this.image_size.TotalReadingImageSizeStr = res.Result.TotalReadingImageSizeStr;
|
|
}
|
|
} catch (err) {
|
|
this.loading = false
|
|
console.log(err)
|
|
}
|
|
},
|
|
// 跳转至上传记录页
|
|
toUpload(row) {
|
|
let query = this.$route.query
|
|
query.siteId = row.TrialSiteId
|
|
query.subjectCode = row.SubjectCode
|
|
query.visitNum = row.VisitNum
|
|
this.$router.push({
|
|
path: '/trials/trials-panel/trial-summary/upload-monitor',
|
|
query
|
|
})
|
|
},
|
|
handleSelectionChange(selection) {
|
|
this.selectArr = selection
|
|
let num = this.selectArr.reduce((sum, item) => sum + item.TotalImageSize, 0)
|
|
if (num <= 0) return this.image_size.CheckImageSize = `0MB`
|
|
this.image_size.CheckImageSize = this.$FormatSize(num)
|
|
},
|
|
// 获取site下拉框数据
|
|
getSite() {
|
|
getTrialSiteSelect(this.$route.query.trialId).then(res => {
|
|
this.siteOptions = res.Result
|
|
})
|
|
},
|
|
changeTimeList() {
|
|
if (this.timeList) {
|
|
this.searchData.BeginScanDate = this.timeList[0]
|
|
this.searchData.EndScanDate = this.timeList[1]
|
|
} else {
|
|
this.searchData.BeginScanDate = null
|
|
this.searchData.EndScanDate = null
|
|
}
|
|
|
|
},
|
|
handleReset() {
|
|
this.searchData = searchDataDefault()
|
|
this.timeList = []
|
|
this.getList()
|
|
},
|
|
handleSearch() {
|
|
this.searchData.PageIndex = 1
|
|
this.getList()
|
|
},
|
|
handleSortChange(column) {
|
|
if (column.order === 'ascending') {
|
|
this.searchData.Asc = true
|
|
} else {
|
|
this.searchData.Asc = false
|
|
}
|
|
let prop = column.prop
|
|
if (prop === 'TotalImageSizeStr') {
|
|
prop = 'TotalImageSize'
|
|
}
|
|
if (prop === 'TotalReadingImageSizeStr') {
|
|
prop = 'TotalReadingImageSize'
|
|
}
|
|
this.searchData.SortField = prop
|
|
this.searchData.PageIndex = 1
|
|
this.getList()
|
|
},
|
|
}
|
|
}
|
|
</script>
|
|
<style lang="scss" scoped>
|
|
.image-summary-wrapper {
|
|
position: relative;
|
|
|
|
.remark {
|
|
position: absolute;
|
|
left: 5px;
|
|
bottom: 7px;
|
|
font-size: 12px;
|
|
|
|
.size {
|
|
display: inline-block;
|
|
min-width: 50px;
|
|
}
|
|
}
|
|
}
|
|
</style> |