hir_web/src/views/trials/trials-panel/reading/reading-tracking/index.vue

596 lines
23 KiB
Vue

<template>
<BaseContainer>
<!-- 搜索框 -->
<template slot="search-container">
<el-form :inline="true">
<!-- 阅片标准 -->
<el-form-item :label="$t('trials:processCfg:form:criterion')">
<el-select v-model="searchData.TrialReadingCriterionId" clearable filterable style="width: 150px">
<el-option v-for="item of CriterionTypeList" :key="item.TrialReadingCriterionId"
:label="item.TrialReadingCriterionName" :value="item.TrialReadingCriterionId" />
</el-select>
</el-form-item>
<!-- 受试者编号 -->
<el-form-item :label="$t('trials:uploadMonitor:table:subjectId')">
<el-input v-model="searchData.SubjectCode" clearable style="width: 140px" />
</el-form-item>
<!-- 患者编号 -->
<el-form-item :label="$t('trials:uploadDicomList:table:pId')">
<el-input v-model="searchData.PatientIdStr" clearable style="width: 140px" />
</el-form-item>
<!-- 患者姓名 -->
<el-form-item :label="$t('trials:uploadDicomList:table:patientName')">
<el-input v-model="searchData.SubjectShortName" clearable style="width: 140px" />
</el-form-item>
<!-- 任务创建时间 -->
<el-form-item :label="$t('trials:reviewTrack:table:createTime')">
<el-date-picker clearable v-model="dateValue2" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']">
</el-date-picker>
</el-form-item>
<!-- 任务状态 -->
<el-form-item :label="$t('trials:readTask:table:taskState')">
<el-select v-model="searchData.taskState" clearable filterable style="width: 150px">
<el-option v-for="item of $d.TaskState" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 阅片状态 -->
<el-form-item :label="$t('trials:readTask:table:readingTaskState')">
<el-select v-model="searchData.ReadingTaskState" clearable filterable style="width: 150px">
<el-option v-for="item of $d.ReadingTaskState" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 阅片完成时间 -->
<el-form-item :label="$t('trials:reviewTrack:table:signTime')">
<el-date-picker clearable v-model="dateValue" type="datetimerange" range-separator="-"
:start-placeholder="$t('trials:uploadClinicalData:table:beginDate')"
:end-placeholder="$t('trials:uploadClinicalData:table:endDate')" :default-time="['00:00:00', '23:59:59']">
</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" icon="el-icon-download" @click="handleExport">
{{ $t('common:button:export') }}
</el-button>
</el-form-item>
</el-form>
</template>
<!-- 阅片管理列表 -->
<template slot="main-container">
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe height="100"
@sort-change="handleSortByColumn" ref="redManagenentTable"
:default-sort="{ prop: 'CreateTime', order: 'descending' }">
<el-table-column type="index" width="40" />
<!-- 受试者编号 -->
<el-table-column prop="SubjectCode" :label="$t('trials:uploadMonitor:table:subjectId')" show-overflow-tooltip
sortable="custom" />
<!-- 患者编号 -->
<el-table-column prop="StudyCode" :label="$t('trials:uploadDicomList:table:pId')" show-overflow-tooltip>
<template slot-scope="scope">
<span v-for="(item, index) in scope.row.PatientList" :key="`${index}${item.PatientId}`">
{{
index === scope.row.PatientList.length - 1
? item.PatientIdStr
: `${item.PatientIdStr}, `
}}
</span>
</template></el-table-column>
<!-- 患者姓名 -->
<el-table-column prop="SubjectShortName" :label="$t('trials:researchStaff:table:Name')" show-overflow-tooltip
sortable="custom" />
<!-- 任务名称 -->
<el-table-column prop="TaskBlindName" :label="$t('trials:auditRecord:table:taskName')" show-overflow-tooltip
sortable="custom" />
<!-- 任务创建时间 -->
<el-table-column prop="CreateTime" :label="$t('trials:reviewTrack:table:createTime')" show-overflow-tooltip
sortable="custom" />
<!-- 任务状态 -->
<el-table-column prop="TaskState" :label="$t('trials:readTask:table:taskState')" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
<el-tag :type="['primary', 'info', '', 'danger', 'warning', 'danger'][
scope.row.TaskState
]
">{{ $fd('TaskState', scope.row.TaskState) }}</el-tag>
</template>
</el-table-column>
<!-- 阅片人 -->
<el-table-column prop="DoctorUser" :label="$t('trials:reviewAssign:searchForm:reader')" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ (scope.row.DoctorUser || {}).UserName }}</span>
</template>
</el-table-column>
<!-- 阅片状态 -->
<el-table-column prop="ReadingTaskState" :label="$t('trials:reviewTrack:table:readingStatus')" width="160"
sortable="custom" show-overflow-tooltip>
<template slot-scope="scope">
<el-tag :type="scope.row.ReadingTaskState === 2 ? 'primary' : 'danger'">{{ $fd('ReadingTaskState',
scope.row.ReadingTaskState) }}</el-tag>
</template>
</el-table-column>
<!-- 阅片完成时间 -->
<el-table-column prop="SignTime" :label="$t('trials:reviewTrack:table:signTime')" show-overflow-tooltip
sortable="custom" />
<!-- 阅片标准 -->
<el-table-column prop="TrialReadingCriterionName" :label="$t('trials:processCfg:form:criterion')"
show-overflow-tooltip sortable="custom" />
<!-- 打包状态 -->
<!-- <el-table-column
prop="PackState"
:label="$t('trials:hirVisit:table:PackState')"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<el-tag
:type="
Number(scope.row.PackState) === 0
? 'danger'
: Number(scope.row.PackState) === 1
? 'warning'
: 'success'
"
>{{ $fd('PackState', Number(scope.row.PackState)) }}</el-tag
>
</template>
</el-table-column> -->
<!-- 建议完成时间 -->
<!-- <el-table-column
prop="StudyCode"
:label="$t('trials:consistencyAnalysis:table:suggesteFinishedTime')"
show-overflow-tooltip
sortable="custom"
/> -->
<!--操作-->
<el-table-column :label="$t('common:action:action')" min-width="210" fixed="right">
<template slot-scope="scope">
<!--阅片结果-->
<el-button circle icon="el-icon-view" :title="$t('trials:auditRecord:table:readingResult')"
@click="readResult(scope.row)" :disabled="scope.row.ReadingTaskState !== 2" />
<!--分享-->
<el-button v-if="OpenImageShare" :disabled="scope.row.ReadingTaskState !== 2" circle
:title="$t('trials:studyList:action:share')" icon="el-icon-share" @click="handleShareImage(scope.row)" />
<!--肿瘤负荷报告-->
<el-button circle icon="el-icon-document" :title="$t('trials:trials-panel:hirVisit:EvaluationReport')"
@click="handleCommand('showReport', scope.row, 'evaluate')"
:disabled="scope.row.ReadingTaskState !== 2 || scope.row.CriterionType === 10" />
<!--疗效评估报告-->
<el-button circle icon="el-icon-document" :title="$t('trials:trials-panel:hirVisit:TumorReport')"
@click="handleCommand('showReport', scope.row, 'tumor')"
:disabled="scope.row.ReadingTaskState !== 2 || scope.row.CriterionType === 10" />
<!--下载影像-->
<el-button circle icon="el-icon-download" :loading="downloading"
:title="$t('trials:reading:button:uploadImages')" @click="
handleCommand('getDownloadSubjectVisitStudyInfo', scope.row)
" />
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
<el-dialog v-if="exportVisible" :title="$t('trials:reviewTrack:button:export')" :visible.sync="exportVisible"
:close-on-click-modal="false" append-to-body>
<exportList :data="searchData" />
</el-dialog>
<base-model :config="share_model">
<template slot="dialog-body">
<div>
<i style="color:#00d1b2;" class="el-icon-success" />
<span>{{ $t('trials:studyList:message:message3') }}</span>
</div>
<div style="margin:10px 0;">
<el-input :maxLength="100" v-model="shareLink" readonly style="width:420px;" />
</div>
<el-form :model="form" :rules="rules" ref="ruleForm" label-width="120px" class="ruleForm">
<el-form-item :label="$t('trials:studyList:message:message2')" prop="extractionCode">
<el-input :maxLength="4" v-model="form.extractionCode" style="width:100px;" clearable
@blur="updateImageShare" />
</el-form-item>
<el-form-item :label="$t('trials:studyList:message:message6')" prop="ImageShareExpireDays">
<el-select v-model="form.ImageShareExpireDays" placeholder="" style="width:100px;"
@change="updateImageShare">
<el-option v-for="item in options" :key="item" :label="item" :value="item">
</el-option>
</el-select>
</el-form-item>
</el-form>
<div>
<el-button type="primary" round @click="copyCode">{{ $t('trials:studyList:message:message4') }}</el-button>
<!-- <el-button type="primary" round @click="updateImageShare">{{ $t('trials:studyList:message:message5')
}}</el-button> -->
</div>
</template>
</base-model>
</template>
</BaseContainer>
</template>
<script>
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import exportList from './components/exportList.vue'
import { getPatientVisitTaskList } from '@/api/readManagenent.js'
import { getToken } from '@/utils/auth'
// import { getSystemConfirmedCreiterionList } from "@/api/trials";
import { getTrialCriterionList } from '@/api/trials/reading'
import { showReadReport, showTumorReport } from '@/api/export'
import { downLoadFile } from '@/utils/stream.js'
import { createImageShare, updateImageShare } from '@/api/share'
import {
getDownloadSubjectVisitStudyInfo,
downloadImageSuccess,
} from '@/api/trials.js'
import BaseModel from '@/components/BaseModel'
const defaultSearchData = () => {
return {
SubjectCode: null,
ReadingCategory: 1,
ReadingTaskState: null,
TaskState: null,
BeginSignTime: null,
EndSignTime: null,
PageIndex: 1,
PageSize: 20,
Asc: false,
SortField: 'CreateTime',
TrialReadingCriterionId: null,
TaskState: null,
SubjectShortName: null,
PatientName: null,
PatientIdStr: null,
PatientSex: null,
BeginTaskCreateTime: null,
EndTaskCreateTime: null,
SubjectShortName: null,
}
}
export default {
name: 'readManagenent',
components: { BaseContainer, Pagination, exportList, BaseModel },
data() {
return {
// 查询
searchData: defaultSearchData(),
dateValue: [],
dateValue2: [],
CriterionTypeList: [],
// 列表
list: [],
loading: false,
total: 0,
// 修改检查
reportFlag: {},
// 下载相关
downloading: false,
downloadId: null,
exportVisible: false,
// 分享
share_model: { visible: false, title: this.$t('trials:studyList:message:message8'), showClose: true, width: '500px' },
form: {
extractionCode: null,
ImageShareExpireDays: null,
},
rules: {
extractionCode: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur,change' },
{
validator: (rule, value, callback) => {
if (value) {
if (value.length !== 4) {
callback(new Error(this.$t('trials:studyList:message:length4')));
}
if (!(/^[a-z0-9]+$/.test(value))) {
callback(new Error(this.$t('trials:studyList:message:testError')));
}
callback();
}
callback();
}
}
],
ImageShareExpireDays: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur,change' },
]
},
shareId: null,
shareLink: null,
options: [1, 7, 15, 30],
OpenImageShare: false
}
},
created() {
this.getList()
this.getTrialConfirmedCreiterionList()
if (localStorage.getItem('CompanyInfo')) {
this.OpenImageShare = JSON.parse(localStorage.getItem('CompanyInfo')).OpenImageShare
}
},
methods: {
async updateImageShare() {
try {
let validate = await this.$refs.ruleForm.validate()
if (!validate) return false
const params = {
ImageShareExpireDays: this.form.ImageShareExpireDays,
Password: this.form.extractionCode,
Id: this.shareId
}
let res = await updateImageShare(params)
if (res.IsSuccess) {
// this.$message.success(this.$t('common:message:updatedSuccessfully'))
return true
}
return false
} catch (err) {
console.log(err)
return false
}
},
handleShareImage(row) {
this.shareLink = ''
this.extractionCode = ''
const params = {
VisitTaskId: row.Id,
RouteUrl: `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.$route.query.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}`
}
this.loading = true
createImageShare(params).then((res) => {
this.loading = false
if (res.IsSuccess) {
// this.shareLink = `${window.location.origin}${window.location.pathname}#/imagesShare?id=${res.Result.ResourceId}`
this.shareLink = `${window.location.origin}/imagesShare?id=${res.Result.ResourceId}`
this.shareId = res.Result.ResourceId
this.form.extractionCode = res.Result.Password
this.form.ImageShareExpireDays = res.Result.ImageShareExpireDays
this.share_model.visible = true
}
}).catch(() => { this.loading = false })
},
// 复制
async copyCode() {
let res = await this.updateImageShare()
if (!res) return false
this.$copyText(`${this.$t('trials:researchRecord:label:link')} ${this.shareLink} ${this.$t('trials:studyList:message:message2')}${this.form.extractionCode}`).then(
res => {
this.$message.success(this.$t('trials:researchRecord:message:copySuccessfully'))
}
).catch(() => { this.$message.error(this.$t('trials:researchRecord:message:copyFailed')) })
},
// 下拉菜单操作
handleCommand(command, item, key) {
this[command](item, key)
},
// 导出
handleExport() {
this.exportVisible = true
},
// 评估报告
async showReport(item, key) {
if (this.reportFlag[item.Id]) return
let data = {
VisitTaskId: item.Id,
}
try {
if (!this.reportFlag.hasOwnProperty(item.Id)) {
this.$set(this.reportFlag, item.Id, true)
}
if (!this.reportFlag[item.Id]) {
this.reportFlag[item.Id] = true
}
let res = null;
if (key === 'evaluate') {
res = await showReadReport(data);
} else {
res = await showTumorReport(data);
}
if (res.IsSuccess) {
let a = document.createElement('a')
let href = this.OSSclientConfig.basePath + res.Result
let fileName = res.Result.split('/')[res.Result.split('/').length - 1]
a.download = fileName
a.href = href
a.click()
URL.revokeObjectURL(href)
this.$nextTick(() => {
a = null
href = null
})
}
this.reportFlag[item.Id] = false
} catch (err) {
this.reportFlag[item.Id] = false
console.log(err)
}
},
// 获取阅片标准
async getTrialConfirmedCreiterionList() {
try {
let trialId = this.$route.query.trialId
let res = await getTrialCriterionList(trialId)
if (res.IsSuccess) {
this.CriterionTypeList = res.Result
}
} catch (err) {
console.log(err)
}
},
// 查询
handleSearch() {
this.getList()
},
// 重置
handleReset() {
this.reset()
this.getList()
},
// 初始化
reset() {
this.searchData = defaultSearchData()
this.dateValue = []
this.dateValue2 = []
this.$refs.redManagenentTable.clearSort()
},
// 排序
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
// 获取列表
async getList() {
try {
this.searchData.TrialId = this.$route.query.trialId
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key]
})
data.TrialId = this.$route.query.trialId
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
data.BeginSignTime = this.$moment(this.dateValue[0]).format(
'YYYY-MM-DD HH:mm:ss'
)
data.EndSignTime = this.$moment(this.dateValue[1]).format(
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.EarliestStudyTime = null
data.LatestStudyTime = null
}
if (this.dateValue2 && this.dateValue2[0] && this.dateValue2[1]) {
data.BeginTaskCreateTime = this.$moment(this.dateValue2[0]).format(
'YYYY-MM-DD HH:mm:ss'
)
data.EndTaskCreateTime = this.$moment(this.dateValue2[1]).format(
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.BeginTaskCreateTime = null
data.EndTaskCreateTime = null
}
this.loading = true
let res = await getPatientVisitTaskList(data)
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 getDownloadSubjectVisitStudyInfo(row) {
if (this.downloading) return
try {
let data = {
SubjectVisitId: row.SourceSubjectVisitId,
TrialId: this.$route.query.trialId,
}
this.downloading = true
let res = await getDownloadSubjectVisitStudyInfo(data)
this.downloading = false
if (res.IsSuccess) {
this.downloadId = res.OtherInfo
this.downloadImage(res.Result)
}
} catch (err) {
this.downloading = false
console.log(err)
}
},
// 打包下载
async downloadImage(data) {
try {
let { files, name } = this.formatDownloadFile(data)
let res = await downLoadFile(files, name, 'zip')
if (res && this.downloadId) {
this.downloadImageSuccess()
}
} catch (err) {
console.log(err)
}
},
// 格式化下载文件路径
formatDownloadFile(data) {
let files = [],
name = `${data.SubjectCode}_${data.VisitName}_ImageStudy.zip`
if (Array.isArray(data.StudyList) && data.StudyList.length > 0) {
data.StudyList.forEach((study) => {
if (Array.isArray(study.SeriesList) && study.SeriesList.length > 0) {
study.SeriesList.forEach((series) => {
if (
Array.isArray(series.InstanceList) &&
series.InstanceList.length > 0
) {
series.InstanceList.forEach((instance) => {
let fileName = instance.Path.split('/').pop()
let obj = {
name: `${data.SubjectCode}_${data.VisitName}/${study.StudyCode
}_${study.StudyTime.split(' ')[0]}_${series.Modality
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
files.push(obj)
})
}
})
}
})
}
return { files, name }
},
// 影像下载成功确认
async downloadImageSuccess() {
try {
let params = {
TrialImageDownloadId: this.downloadId,
}
await downloadImageSuccess(params)
} catch (err) {
console.log(err)
}
},
// 阅片结果
readResult(row) {
if (this.openWindow) {
this.openWindow.close()
}
var token = getToken()
var path
// if (row.ReadingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId
}&trialId=${this.$route.query.trialId}&subjectCode=${row.SubjectCode
}&subjectId=${row.SubjectId}&visitTaskId=${row.Id
}&isReadingTaskViewInOrder=${true}&criterionType=${row.CriterionType
}&readingTool=${row.ReadingTool}&TokenKey=${token}`
// } else {
// path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`;
// }
// const routeData = this.$router.resolve({
// path: `/readingPage?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.Id}&TokenKey=${token}`
// })
this.openWindow = window.open(path, '_blank')
},
},
}
</script>