Compare commits
No commits in common. "65da9636a20ce4d8d97c4e92ab69eb4d68da97c1" and "b786c5e656468e3c224c80f407f2ec6fe72db9ae" have entirely different histories.
65da9636a2
...
b786c5e656
|
@ -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,
|
||||||
|
|
|
@ -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()
|
||||||
// 设置页面标题
|
// 设置页面标题
|
||||||
|
|
|
@ -9,9 +9,6 @@ const getDefaultState = () => {
|
||||||
studyListQuery: null,
|
studyListQuery: null,
|
||||||
unlock: false,
|
unlock: false,
|
||||||
config: {},
|
config: {},
|
||||||
uploadTip: null,
|
|
||||||
timer: null,
|
|
||||||
whiteList: []
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
|
@ -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");
|
||||||
},
|
},
|
||||||
|
|
|
@ -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}`,
|
||||||
|
|
Loading…
Reference in New Issue