503 lines
16 KiB
Vue
503 lines
16 KiB
Vue
<template>
|
||
<BaseContainer>
|
||
<!-- 搜索框 -->
|
||
<template slot="search-container">
|
||
<el-form :inline="true">
|
||
<!-- 受试者编号 -->
|
||
<el-form-item :label="$t('trials:crcQuestion:table:subjectId')">
|
||
<el-input
|
||
v-model="searchData.SubjectCode"
|
||
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:subject:table:gender')">
|
||
<el-select
|
||
v-model="searchData.SubjectSex"
|
||
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-form-item>
|
||
<!-- 访视名称 -->
|
||
<!-- <el-form-item :label="$t('trials:globalReview:table:visitName')">
|
||
<el-select
|
||
v-model="searchData.SiteId"
|
||
clearable
|
||
filterable
|
||
style="width: 150px"
|
||
>
|
||
<el-option
|
||
v-for="item of visitOptions"
|
||
:key="item.SiteId"
|
||
:label="item.TrialSiteCode"
|
||
:value="item.SiteId"
|
||
/>
|
||
</el-select>
|
||
</el-form-item> -->
|
||
<!-- 状态 -->
|
||
<!-- <el-form-item :label="$t('trials:trials-list:table:status')">
|
||
<el-select
|
||
v-model="searchData.SiteId"
|
||
clearable
|
||
filterable
|
||
style="width: 150px"
|
||
>
|
||
<el-option
|
||
v-for="item of siteOptions"
|
||
:key="item.SiteId"
|
||
:label="item.TrialSiteCode"
|
||
:value="item.SiteId"
|
||
/>
|
||
</el-select>
|
||
</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-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"
|
||
>
|
||
<el-table-column width="40">
|
||
<template>
|
||
<i
|
||
class="el-icon-warning-outline"
|
||
:title="$t('trials:hirVisit:tipMessage:tipOne')"
|
||
style="color: red"
|
||
></i>
|
||
</template>
|
||
</el-table-column>
|
||
<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="PatientList.PatientIdStr"
|
||
: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:uploadDicomList:table:patientName')"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 性别 -->
|
||
<el-table-column
|
||
prop="SubjectSex"
|
||
:label="$t('trials:subject:table:gender')"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 访视名称 -->
|
||
<el-table-column
|
||
prop="VisitName"
|
||
:label="$t('trials:uploadMonitor:table:visitName')"
|
||
show-overflow-tooltip
|
||
/>
|
||
<!-- 数据收集 -->
|
||
<!-- <el-table-column
|
||
prop="StudyCode"
|
||
:label="$t('trials:crcUpload:table:dataCollected')"
|
||
show-overflow-tooltip
|
||
/> -->
|
||
<!-- 最早拍片日期 -->
|
||
<el-table-column
|
||
prop="VisitEarliestStudyTime"
|
||
:label="$t('trials:trials-panel:table:EarliestScanDate')"
|
||
show-overflow-tooltip
|
||
sortable="custom"
|
||
/>
|
||
<!-- 最晚拍片日期 -->
|
||
<el-table-column
|
||
prop="VisitLatestStudyTime"
|
||
:label="$t('trials:linkedRP:table:latestScanDate')"
|
||
show-overflow-tooltip
|
||
sortable="custom"
|
||
/>
|
||
<!-- 状态 -->
|
||
<el-table-column
|
||
prop="SubmitState"
|
||
:label="$t('trials:trials-list:table:status')"
|
||
show-overflow-tooltip
|
||
sortable="custom"
|
||
>
|
||
<template slot-scope="scope">
|
||
<el-tag v-if="scope.row.SubmitState * 1 === 0" type="warning">{{
|
||
$fd("SubmitState", scope.row.SubmitState * 1)
|
||
}}</el-tag>
|
||
<el-tag v-else-if="scope.row.SubmitState * 1 === 1" type="danger">{{
|
||
$fd("SubmitState", scope.row.SubmitState * 1)
|
||
}}</el-tag>
|
||
<el-tag v-else-if="scope.row.SubmitState * 1 === 2">{{
|
||
$fd("SubmitState", scope.row.SubmitState * 1)
|
||
}}</el-tag>
|
||
</template>
|
||
</el-table-column>
|
||
<!-- 提交时间 -->
|
||
<el-table-column
|
||
prop="SubmitTime"
|
||
:label="$t('trials:crcUpload:table:submitTime')"
|
||
show-overflow-tooltip
|
||
sortable="custom"
|
||
/>
|
||
<!--操作-->
|
||
<el-table-column
|
||
:label="$t('common:action:action')"
|
||
min-width="100"
|
||
fixed="right"
|
||
v-if="
|
||
hasPermi(['trials:trials-panel:hirVisit:edit']) ||
|
||
hasPermi(['trials:trials-panel:hirVisit:submit']) ||
|
||
hasPermi(['trials:trials-panel:hirVisit:remove']) ||
|
||
hasPermi(['trials:trials-panel:hirVisit:result']) ||
|
||
hasPermi(['trials:trials-panel:hirVisit:downlaod'])
|
||
"
|
||
>
|
||
<template slot-scope="scope">
|
||
<!--修改检查-->
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['trials:trials-panel:hirVisit:edit']"
|
||
@click.stop="editStudy(scope.row)"
|
||
>{{ $t("trials:hirVisit:button:editStudy") }}</el-button
|
||
>
|
||
<!--提交-->
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['trials:trials-panel:hirVisit:submit']"
|
||
@click.stop="submit(scope.row)"
|
||
>{{ $t("common:button:submit") }}</el-button
|
||
>
|
||
<!--删除-->
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['trials:trials-panel:hirVisit:remove']"
|
||
@click.stop="remove(scope.row)"
|
||
>{{ $t("common:button:delete") }}</el-button
|
||
>
|
||
<!--评估结果-->
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['trials:trials-panel:hirVisit:result']"
|
||
@click.stop="result(scope.row)"
|
||
>{{ $t("trials:adReview:title:result") }}</el-button
|
||
>
|
||
<!--下载影像-->
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['trials:trials-panel:hirVisit:download']"
|
||
@click.stop="downloadImage(scope.row)"
|
||
>{{ $t("trials:reading:button:uploadImages") }}</el-button
|
||
>
|
||
<!--下载医疗报告-->
|
||
<el-button
|
||
type="text"
|
||
v-hasPermi="['trials:trials-panel:hirVisit:download']"
|
||
@click.stop="downloadReport(scope.row)"
|
||
>{{ $t("trials:reading:button:uploadReport") }}</el-button
|
||
>
|
||
</template>
|
||
</el-table-column>
|
||
</el-table>
|
||
|
||
<!-- 分页组件 -->
|
||
<pagination
|
||
class="page"
|
||
:total="total"
|
||
:page.sync="searchData.PageIndex"
|
||
:limit.sync="searchData.PageSize"
|
||
@pagination="getList"
|
||
/>
|
||
</template>
|
||
<!--修改检查-->
|
||
<editStudyList
|
||
:visible.sync="editStudyVisible"
|
||
:data="editStudyData"
|
||
v-if="editStudyVisible"
|
||
/>
|
||
</BaseContainer>
|
||
</template>
|
||
<script>
|
||
import BaseContainer from "@/components/BaseContainer";
|
||
import Pagination from "@/components/Pagination";
|
||
import editStudyList from "./components/edit-study-list.vue";
|
||
import {
|
||
getPatientSubejctVisitList,
|
||
getSubjectImageZipInfo,
|
||
} from "@/api/trials/visit.js";
|
||
import { submitVisitStudyBinding } from "@/api/inspection.js";
|
||
import JSZip from "jszip";
|
||
import axios from "axios";
|
||
import { saveAs } from "file-saver";
|
||
const defaultSearchData = () => {
|
||
return {
|
||
subjectCode: null,
|
||
subjectShortName: null,
|
||
subjectSex: null,
|
||
pageIndex: 1,
|
||
pageSize: 20,
|
||
asc: false,
|
||
sortField: "SubmitTime",
|
||
};
|
||
};
|
||
export default {
|
||
name: "hirVisit",
|
||
components: { BaseContainer, Pagination, editStudyList },
|
||
data() {
|
||
return {
|
||
// 查询
|
||
searchData: defaultSearchData(),
|
||
visitOptions: [],
|
||
// 列表
|
||
list: [
|
||
{
|
||
StudyCode: 1,
|
||
},
|
||
],
|
||
loading: false,
|
||
total: 0,
|
||
// 修改检查
|
||
editStudyVisible: false,
|
||
editStudyData: {},
|
||
};
|
||
},
|
||
created() {
|
||
this.getList();
|
||
},
|
||
methods: {
|
||
// 查询
|
||
handleSearch() {
|
||
this.getList();
|
||
},
|
||
// 重置
|
||
handleReset() {
|
||
this.searchData = defaultSearchData();
|
||
this.getList();
|
||
},
|
||
// 排序
|
||
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() {
|
||
let data = {};
|
||
Object.keys(this.searchData).forEach((key) => {
|
||
data[key] = this.searchData[key];
|
||
});
|
||
data.TrialId = this.$route.query.trialId;
|
||
try {
|
||
this.loading = true;
|
||
let res = await getPatientSubejctVisitList(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);
|
||
}
|
||
},
|
||
// 修改检查
|
||
editStudy(item) {
|
||
this.editStudyData = item;
|
||
this.editStudyVisible = true;
|
||
},
|
||
// 提交
|
||
async submit(item) {
|
||
let confirm = await this.$confirm(
|
||
this.$t("trials:adjustRecord:message:confirm"),
|
||
{
|
||
type: "warning",
|
||
distinguishCancelAndClose: true,
|
||
confirmButtonText: this.$t("common:button:confirm"),
|
||
cancelButtonText: this.$t("recompose:button:cancel"),
|
||
}
|
||
);
|
||
if (confirm !== "confirm") return;
|
||
let data = {
|
||
TrialId: this.$route.query.trialId,
|
||
SubjectVisitId: [item.SubjectVisitId],
|
||
};
|
||
try {
|
||
this.loading = true;
|
||
let res = await submitVisitStudyBinding(data);
|
||
this.loading = false;
|
||
if (res.IsSuccess) {
|
||
this.$message.success(
|
||
this.$t("trials:crcUpload:message:submittedSuccessfully")
|
||
);
|
||
}
|
||
} catch (err) {
|
||
this.btnLoading2 = false;
|
||
console.log(err);
|
||
}
|
||
},
|
||
// 删除
|
||
remove() {},
|
||
// 评估结果
|
||
result() {},
|
||
// 下载报告
|
||
downloadReport() {},
|
||
// 下载影像
|
||
async downloadImage(item) {
|
||
try {
|
||
let res = await getSubjectImageZipInfo(item.SubjectId);
|
||
if (res.IsSuccess) {
|
||
let item = res.Result;
|
||
await this.setfolder(item);
|
||
}
|
||
} catch (err) {
|
||
console.log(err);
|
||
}
|
||
},
|
||
async setfolder(item) {
|
||
const zip = new JSZip(); // 创建实例对象
|
||
let zipObj = {};
|
||
const promises = [];
|
||
for (let patient of item.PatientList) {
|
||
if (!zipObj[patient.PatientIdStr]) {
|
||
zipObj[patient.PatientIdStr] = zip.folder(patient.PatientIdStr);
|
||
console.log(zipObj[patient.PatientIdStr]);
|
||
}
|
||
for (let visit of patient.VisitList) {
|
||
for (let study of visit.StudyList) {
|
||
let date = study.StudyTime.split(" ")[0];
|
||
if (!zipObj[`${patient.PatientIdStr}${date}`]) {
|
||
zipObj[`${patient.PatientIdStr}${date}`] =
|
||
zipObj[patient.PatientIdStr].folder(date);
|
||
}
|
||
for (let series of study.SeriesList) {
|
||
if (!zipObj[`${patient.PatientIdStr}${date}${series.Modality}`]) {
|
||
zipObj[`${patient.PatientIdStr}${date}${series.Modality}`] =
|
||
zipObj[`${patient.PatientIdStr}${date}`].folder(
|
||
series.Modality
|
||
);
|
||
}
|
||
for (let instance of series.InstancePathList) {
|
||
let obj = {
|
||
subjectCode: item.SubjectCode,
|
||
patientIdStr: patient.PatientIdStr,
|
||
visitName: visit.VisitName,
|
||
date: study.StudyTime.split(" ")[0],
|
||
modality: series.Modality,
|
||
instancePath: instance.Path,
|
||
dicomName: instance.Path.split("/Dicom/")[1],
|
||
};
|
||
const promise = this.handleBatchDown(
|
||
obj,
|
||
zipObj[`${patient.PatientIdStr}${date}${series.Modality}`]
|
||
);
|
||
promises.push(promise);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// 生成 zip 文件
|
||
Promise.all(promises)
|
||
.then(() => {
|
||
// 生成zip 文件
|
||
zip
|
||
.generateAsync({
|
||
type: "blob",
|
||
compression: "DEFLATE", // STORE: 默认不压缩, DEFLATE:需要压缩
|
||
compressionOptions: {
|
||
level: 9, // 压缩等级 1~9 1 压缩速度最快, 9 最优压缩方式
|
||
},
|
||
})
|
||
.then((res) => {
|
||
saveAs(res, item.SubjectCode + new Date().getTime() + "_CV.zip"); // 使用FileSaver.saveAs保存文件,文件名可自定义
|
||
zipObj = null;
|
||
});
|
||
})
|
||
.catch((reason) => {});
|
||
},
|
||
async handleBatchDown(item, zip) {
|
||
return new Promise((resolve) => {
|
||
let path = `/${item.subjectCode}_${item.patientIdStr}/${item.visitName}/${item.date}_${item.modality}${item.instancePath}`;
|
||
this.getFileData(
|
||
this.OSSclientConfig.basePath + path
|
||
// "https://th.bing.com/th/id/OIP.duz6S7Fvygrqd6Yj_DcXAQHaF7?rs=1&pid=ImgDetMain"
|
||
).then((res) => {
|
||
const fileName = item.dicomName + ".dcm";
|
||
zip.file(fileName, res.data, { binary: true });
|
||
resolve();
|
||
});
|
||
});
|
||
},
|
||
getFileData(fileUrl) {
|
||
return new Promise((resolve, reject) => {
|
||
axios(fileUrl, {
|
||
method: "GET",
|
||
responseType: "blob", // 返回的数据会被强制转为blob类型 ,转换成arraybuffer 也行
|
||
})
|
||
.then((res) => {
|
||
resolve(res);
|
||
})
|
||
.catch((error) => {
|
||
reject(error);
|
||
});
|
||
});
|
||
},
|
||
},
|
||
};
|
||
</script>
|