Compare commits

..

No commits in common. "65da9636a20ce4d8d97c4e92ab69eb4d68da97c1" and "b786c5e656468e3c224c80f407f2ec6fe72db9ae" have entirely different histories.

6 changed files with 151 additions and 111 deletions

View File

@ -111,9 +111,7 @@ export default {
async handler() { async handler() {
if ( if (
this.$route.query.trialId && this.$route.query.trialId &&
this.$route.query.trialId !== this.$route.query.trialId !== this.$store.state.trials.config.trialId
this.$store.state.trials.config.trialId &&
this.$store.state.trials.whiteList.indexOf(this.$route.path) === -1
) { ) {
let res = await getTrialExtralConfig({ let res = await getTrialExtralConfig({
TrialId: this.$route.query.trialId, TrialId: this.$route.query.trialId,

View File

@ -11,7 +11,7 @@ import { OSSclient } from './utils/oss'
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
const whiteList = ['/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms'] const whiteList = ['/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
store.state.trials.whiteList = whiteList;
router.beforeEach(async (to, from, next) => { router.beforeEach(async (to, from, next) => {
NProgress.start() NProgress.start()
// 设置页面标题 // 设置页面标题

View File

@ -9,9 +9,6 @@ const getDefaultState = () => {
studyListQuery: null, studyListQuery: null,
unlock: false, unlock: false,
config: {}, config: {},
uploadTip: null,
timer: null,
whiteList: []
} }
} }

View File

@ -1,21 +1,17 @@
import JSZip from "jszip";
import { saveAs } from "file-saver";
import Vue from 'vue'; import Vue from 'vue';
import { import {
requestPackageAndAnonymizImage, requestPackageAndAnonymizImage,
} from "@/api/load.js"; } from "@/api/load.js";
import streamSaver from "streamsaver"; import streamSaver from "streamsaver";
import "streamsaver/examples/zip-stream.js" import "streamsaver/examples/zip-stream.js"
import store from '@/store';
let flag = {}; let flag = {};
export const resetFlag = () => { export const resetFlag = () => {
flag = {}; flag = {}
if (store.state.trials.timer) {
clearInterval(store.state.trials.timer);
store.state.trials.timer = null;
}
} }
export const downloadImage = async (id, id2, IsDicom = true) => { export const downloadImage = async (id, id2, IsDicom = true) => {
// if (flag[`${id2}_${IsDicom}`]) return Vue.prototype.$message.warning(Vue.prototype.$t('trials:upload:tip:uploading')); if (flag[`${id2}_${IsDicom}`]) return Vue.prototype.$message.warning(Vue.prototype.$t('trials:upload:tip:uploading'));
if (flag[`${id2}_${IsDicom}`]) return false;
flag[`${id2}_${IsDicom}`] = true flag[`${id2}_${IsDicom}`] = true
try { try {
let params = { let params = {
@ -27,42 +23,26 @@ export const downloadImage = async (id, id2, IsDicom = true) => {
if (res.IsSuccess) { if (res.IsSuccess) {
if (!res.Result) { if (!res.Result) {
flag[`${id2}_${IsDicom}`] = false; flag[`${id2}_${IsDicom}`] = false;
// Vue.prototype.$message.warning(Vue.prototype.$t("trials:upload:message:not")) Vue.prototype.$message.warning(Vue.prototype.$t("trials:upload:message:not"))
let message = Vue.prototype.$t('trials:upload:tip:uploading').replace("xxx", res.OtherInfo.FileName); return 1;
store.state.trials.uploadTip = message;
console.log(store.state.trials.timer)
if (!store.state.trials.timer) {
store.state.trials.timer = setInterval(() => {
downloadImage(id, id2, IsDicom);
}, 2000);
}
return false;
} }
if (store.state.trials.timer) { Vue.prototype.$message.success(Vue.prototype.$t("trials:upload:message:startUpload"));
clearInterval(store.state.trials.timer);
store.state.trials.timer = null;
}
let fileName = res.Result.split("/").pop();
let href = Vue.prototype.OSSclientConfig.basePath + res.Result; let href = Vue.prototype.OSSclientConfig.basePath + res.Result;
if (fileName !== res.OtherInfo.FileName) { download(href, res.OtherInfo.FileName, { id2, IsDicom })
let message = Vue.prototype.$t('trials:upload:tip:uploading').replace("xxx", res.OtherInfo.FileName); return 2;
store.state.trials.uploadTip = message; // let a = document.createElement("a");
// Vue.prototype.$message.success(Vue.prototype.$t("trials:upload:message:startUpload")); // // let fileName =
return download(href, res.OtherInfo.FileName, { id2, IsDicom }); // // res.Result.split("/")[res.Result.split("/").length - 1];
// a.download = res.OtherInfo.FileName;
} // a.href = href;
let a = document.createElement("a"); // a.click();
a.download = res.OtherInfo.FileName; // URL.revokeObjectURL(href);
a.href = href; // let timer = setTimeout(() => {
a.click(); // a = null;
URL.revokeObjectURL(href); // href = null;
let timer = setTimeout(() => { // timer = null;
a = null; // }, 500)
href = null; // return 2;
timer = null;
}, 500)
store.state.trials.uploadTip = null;
return true;
} else { } else {
flag[`${id2}_${IsDicom}`] = false; flag[`${id2}_${IsDicom}`] = false;
return false; return false;
@ -72,6 +52,118 @@ export const downloadImage = async (id, id2, IsDicom = true) => {
console.log(err); console.log(err);
} }
}; };
const setfolder = async (item) => {
const zip = new JSZip(); // 创建实例对象
let patientIds = item.PatientList.map(i => i.PatientIdStr);
let zipName = `${item.SubjectCode}_${patientIds.join(',')}`;
let zipObj = {};
const promises = [];
for (let visit of item.VisitList) {
if (!zipObj[`${visit.VisitName}`]) {
zipObj[`${visit.VisitName}`] = zip.folder(visit.VisitName);
}
for (let study of visit.StudyList) {
let date = study.StudyTime.split(" ")[0];
for (let series of study.SeriesList) {
if (
!zipObj[
`${visit.VisitName}${series.Modality}`
]
) {
zipObj[
`${visit.VisitName}${series.Modality}`
] = zipObj[`${visit.VisitName}`].folder(
`${date}_${series.Modality}`
);
}
for (let instance of series.InstancePathList) {
let obj = {
subjectCode: item.SubjectCode,
visitName: visit.VisitName,
date: study.StudyTime.split(" ")[0],
modality: series.Modality,
instancePath: instance.Path,
dicomName: instance.Path.split("/Dicom/")[1],
};
const promise = handleBatchDown(
obj,
zipObj[
`${visit.VisitName}${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, zipName + ".zip"); // 使用FileSaver.saveAs保存文件文件名可自定义
flag[`${id2}_${IsDicom}`] = false;
zipObj = null;
});
})
.catch((reason) => { flag[`${id2}_${IsDicom}`] = false; });
};
const handleBatchDown = async (item, zip) => {
return new Promise((resolve) => {
console.log("同步下载打包开始时间:" + new Date());
// 创建压缩文件输出流
const zipFileOutputStream = streamSaver.createWriteStream(zipName);
// 创建下载文件流
const fileIterator = files.values();
const readableZipStream = new window.ZIP({
async pull(ctrl) {
const fileInfo = fileIterator.next();
if (fileInfo.done) {//迭代终止
ctrl.close();
} else {
const { name, url } = fileInfo.value;
return fetch(url).then(res => {
ctrl.enqueue({
name,
stream: () => res.body
})
})
}
}
});
if (window.WritableStream && readableZipStream.pipeTo) {
// 开始下载
readableZipStream
.pipeTo(zipFileOutputStream)
.then(() => { console.log("同步下载打包结束时间:" + new Date()); resolve(true) })
} else {
resolve(false);
}
})
};
const getFileData = (fileUrl) => {
return new Promise((resolve, reject) => {
axios(fileUrl, {
method: "GET",
responseType: "blob", // 返回的数据会被强制转为blob类型 转换成arraybuffer 也行
})
.then((res) => {
resolve(res);
})
.catch((error) => {
reject(error);
});
});
};
export const fileDownload = (content, filename) => { export const fileDownload = (content, filename) => {
const eleLink = document.createElement("a"); const eleLink = document.createElement("a");
eleLink.download = filename; eleLink.download = filename;
@ -85,9 +177,7 @@ export const fileDownload = (content, filename) => {
let download = async (downloadUrl, downloadFileName, res) => { let download = async (downloadUrl, downloadFileName, res) => {
const blob = await getBlob(downloadUrl); const blob = await getBlob(downloadUrl);
flag[`${res.id2}_${res.IsDicom}`] = false; flag[`${res.id2}_${res.IsDicom}`] = false;
store.state.trials.uploadTip = null;
saveAsB(blob, downloadFileName); saveAsB(blob, downloadFileName);
return true;
} }
let getBlob = (url) => { let getBlob = (url) => {
@ -127,39 +217,3 @@ let saveAsB = (blob, filename) => {
window.URL.revokeObjectURL(link.href); window.URL.revokeObjectURL(link.href);
} }
// 前端流式打包下载
const handleBatchDown = async (item, zip) => {
return new Promise((resolve) => {
console.log("同步下载打包开始时间:" + new Date());
// 创建压缩文件输出流
const zipFileOutputStream = streamSaver.createWriteStream(zipName);
// 创建下载文件流
const fileIterator = files.values();
const readableZipStream = new window.ZIP({
async pull(ctrl) {
const fileInfo = fileIterator.next();
if (fileInfo.done) {//迭代终止
ctrl.close();
} else {
const { name, url } = fileInfo.value;
return fetch(url).then(res => {
ctrl.enqueue({
name,
stream: () => res.body
})
})
}
}
});
if (window.WritableStream && readableZipStream.pipeTo) {
// 开始下载
readableZipStream
.pipeTo(zipFileOutputStream)
.then(() => { console.log("同步下载打包结束时间:" + new Date()); resolve(true) })
} else {
resolve(false);
}
})
};

View File

@ -260,7 +260,7 @@ export default {
image(item) { image(item) {
let token = getToken(); let token = getToken();
const routeData = this.$router.resolve({ const routeData = this.$router.resolve({
path: `/showdicom?studyId=${item.SCPStudyId}&TokenKey=${token}&type=Study`, path: `/showdicom?studyId=${item.SCPStudyId}&TokenKey=${token}&type=Patient`,
}); });
this.newWindow = window.open(routeData.href, "_blank"); this.newWindow = window.open(routeData.href, "_blank");
}, },

View File

@ -42,13 +42,7 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div style="text-align: right; position: relative"> <div style="text-align: right">
<div
class="uploadTip"
style="position: absolute; top: 0; left: 0"
>
{{ $store.state.trials.uploadTip }}
</div>
<!-- 下载所有影像 --> <!-- 下载所有影像 -->
<el-button <el-button
v-if="$store.state.trials.config.IsSupportQCDownloadImage" v-if="$store.state.trials.config.IsSupportQCDownloadImage"
@ -300,13 +294,7 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div style="text-align: right; position: relative"> <div style="text-align: right">
<div
class="uploadTip"
style="position: absolute; top: 0; left: 0"
>
{{ $store.state.trials.uploadTip }}
</div>
<!-- 下载所有影像 --> <!-- 下载所有影像 -->
<el-button <el-button
v-if="$store.state.trials.config.IsSupportQCDownloadImage" v-if="$store.state.trials.config.IsSupportQCDownloadImage"
@ -378,10 +366,7 @@
<!-- 预览 --> <!-- 预览 -->
<el-button <el-button
type="text" type="text"
:disabled=" :disabled="files.row.FileType && files.row.FileType.indexOf('zip') >= 0"
files.row.FileType &&
files.row.FileType.indexOf('zip') >= 0
"
@click.native.prevent="previewFile(files.row)" @click.native.prevent="previewFile(files.row)"
> >
{{ $t("trials:audit:button:nonDicomsPreview") }} {{ $t("trials:audit:button:nonDicomsPreview") }}
@ -1233,7 +1218,7 @@ import SignForm from "@/views/trials/components/newSignForm";
import { getToken } from "@/utils/auth"; import { getToken } from "@/utils/auth";
import const_ from "@/const/sign-code"; import const_ from "@/const/sign-code";
import uploadPetClinicalData from "@/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue"; import uploadPetClinicalData from "@/views/trials/trials-panel/visit/crc-upload/components/uploadPetClinicalData.vue";
import { downloadImage, resetFlag } from "@/utils/uploadZip.js"; import { downloadImage , resetFlag } from "@/utils/uploadZip.js";
export default { export default {
name: "QualityAssurance", name: "QualityAssurance",
components: { components: {
@ -1346,6 +1331,9 @@ export default {
BodyPart: {}, BodyPart: {},
}; };
}, },
beforeDestroy(){
resetFlag();
},
async mounted() { async mounted() {
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId); this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId);
if (this.disabled) { if (this.disabled) {
@ -1366,13 +1354,16 @@ export default {
if (this.open) { if (this.open) {
this.open.close(); this.open.close();
} }
resetFlag();
}, },
methods: { methods: {
// //
async downloadImage(IsDicom) { async downloadImage(IsDicom) {
try { try {
await downloadImage(this.$route.query.trialId, this.data.Id, IsDicom); await downloadImage(
this.$route.query.trialId,
this.data.Id,
IsDicom
);
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
@ -2238,7 +2229,7 @@ export default {
this.open.close(); this.open.close();
} }
// this.previewAllNoneDicomVisible = true // this.previewAllNoneDicomVisible = true
let trialId = this.$route.query.trialId; let trialId = this.$route.query.trialId
var token = getToken(); var token = getToken();
const routeData = this.$router.resolve({ const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&TokenKey=${token}`, path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&TokenKey=${token}`,
@ -2250,7 +2241,7 @@ export default {
if (this.open) { if (this.open) {
this.open.close(); this.open.close();
} }
let trialId = this.$route.query.trialId; let trialId = this.$route.query.trialId
var token = getToken(); var token = getToken();
const routeData = this.$router.resolve({ const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&studyId=${row.Id}&TokenKey=${token}`, path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${this.data.Id}&studyId=${row.Id}&TokenKey=${token}`,