上传、下载添加提示;非dicom添加上传监控
continuous-integration/drone/push Build is passing Details

uat_us
DESKTOP-6C3NK6N\WXS 2024-09-12 14:22:52 +08:00
parent e845fdaad4
commit 986bce36e6
7 changed files with 650 additions and 461 deletions

View File

@ -37,6 +37,10 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<div class="tip">
<i class="el-icon-warning-outline"></i>
<div v-html="$t('download:tip:message')"></div>
</div>
<!--上传列表@selection-change="handleSelectionChange"--> <!--上传列表@selection-change="handleSelectionChange"-->
<el-table <el-table
ref="dicomFilesTable" ref="dicomFilesTable"
@ -464,4 +468,12 @@ export default {
justify-content: space-between; justify-content: space-between;
margin: 10px 0; margin: 10px 0;
} }
.tip {
display: flex;
align-items: flex-start;
margin-top: 5px;
i {
margin: 3px 5px 0 0;
}
}
</style> </style>

View File

@ -1,32 +1,10 @@
<template> <template>
<div> <div>
<div class="top"> <div>
<span>{{ $t('upload:dicom:title') }}</span> <span>{{ $t('upload:dicom:title') }}</span>
<div class="btnBox"> <div class="tip">
<form id="inputForm" ref="uploadForm" enctype="multipart/form-data"> <i class="el-icon-warning-outline"></i>
<div class="form-group"> <div v-html="$t('upload:dicom:tip:message1')"></div>
<div id="directoryInputWrapper" class="btn btn-link file-input">
<el-button
type="primary"
:disabled="btnLoading"
:loading="btnLoading"
size="mini"
>
{{ $t('upload:dicom:button:upload') }}
</el-button>
<input
type="file"
name="file"
ref="pathClear"
:disabled="btnLoading"
webkitdirectory
multiple
title=""
@change="beginScanFiles($event)"
/>
</div>
</div>
</form>
</div> </div>
</div> </div>
<!--检查列表--> <!--检查列表-->
@ -137,9 +115,37 @@
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="margin: 10px 0"> <div style="margin: 10px 0" class="top">
<span>{{ $t('upload:dicom:uploadTitle') }}</span> <span>{{ $t('upload:dicom:uploadTitle') }}</span>
<span style="margin-left: 10px">{{ $store.state.trials.uploadTip }}</span> <div class="btnBox">
<span style="margin-right: 10px">
{{ $store.state.trials.uploadTip }}
</span>
<form id="inputForm" ref="uploadForm" enctype="multipart/form-data">
<div class="form-group">
<div id="directoryInputWrapper" class="btn btn-link file-input">
<el-button
type="primary"
:disabled="btnLoading"
:loading="btnLoading"
size="mini"
>
{{ $t('upload:dicom:button:upload') }}
</el-button>
<input
type="file"
name="file"
ref="pathClear"
:disabled="btnLoading"
webkitdirectory
multiple
title=""
@change="beginScanFiles($event)"
/>
</div>
</div>
</form>
</div>
</div> </div>
<!--上传列表--> <!--上传列表-->
<el-table <el-table
@ -1515,4 +1521,12 @@ export default {
opacity: 0; opacity: 0;
cursor: pointer; cursor: pointer;
} }
.tip {
display: flex;
align-items: flex-start;
margin-top: 5px;
i {
margin: 3px 5px 0 0;
}
}
</style> </style>

View File

@ -2,12 +2,16 @@
<div class="nonedicomFile"> <div class="nonedicomFile">
<div class="top"> <div class="top">
<span>{{ $t('upload:nonedicom:title') }}</span> <span>{{ $t('upload:nonedicom:title') }}</span>
<div class="tip">
<i class="el-icon-warning-outline"></i>
<div v-html="$t('upload:nonedicom:tip:message')"></div>
</div>
</div> </div>
<!--检查列表--> <!--检查列表-->
<el-table <el-table
:data="list" :data="list"
style="width: 100%" style="width: 100%"
v-adaptive="{ bottomOffset: 40 }" v-adaptive="{ bottomOffset: 60 }"
:loading="loading" :loading="loading"
@sort-change="handleSortByColumn" @sort-change="handleSortByColumn"
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }" :default-sort="{ prop: 'TaskBlindName', order: 'descending' }"
@ -624,6 +628,7 @@ export default {
let res = await preArchiveStudy({ let res = await preArchiveStudy({
subjectVisitId: this.currentRow.SourceSubjectVisitId, subjectVisitId: this.currentRow.SourceSubjectVisitId,
isDicom: false, isDicom: false,
FileCount: this.selectArr.length,
}) })
if (res.IsSuccess) { if (res.IsSuccess) {
this.studyMonitorId = res.Result this.studyMonitorId = res.Result
@ -643,16 +648,15 @@ export default {
if (!this.uploadVisible) return if (!this.uploadVisible) return
let file = this.fileList.filter((item) => item.id === arr[index].id)[0] let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
file.status = 1 file.status = 1
console.log(file)
let path = `/${this.$route.query.trialId}/TaskImage/${ let path = `/${this.$route.query.trialId}/TaskImage/${
this.currentRow.SubjectId this.currentRow.SubjectId
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name }/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
.substring(file.name.lastIndexOf('.')) .substring(file.name.lastIndexOf('.'))
.toLocaleLowerCase()}` .toLocaleLowerCase()}`
console.log(path) file.curPath = path
const fileData = await this.fileToBlob(file.file) const fileData = await this.fileToBlob(file.file)
let res = await this.fileToOss(path, fileData, file) let res = await this.fileToOss(path, fileData, file)
if (res) { if (res && index <= 3) {
file.status = 2 file.status = 2
this.successFileList.push({ this.successFileList.push({
fileName: file.name, fileName: file.name,
@ -662,7 +666,8 @@ export default {
}) })
let flag = arr.every((item) => item.status === 2) let flag = arr.every((item) => item.status === 2)
if (flag) { if (flag) {
return this.submitFile(this.successFileList) let RecordPath = await this.uploadRecord(arr)
return this.submitFile(this.successFileList, RecordPath)
} }
} else { } else {
file.status = 3 file.status = 3
@ -671,12 +676,14 @@ export default {
if (flag) { if (flag) {
let failFileList = arr.filter((item) => item.status === 3) let failFileList = arr.filter((item) => item.status === 3)
if (failFileList && failFileList.length > 0) { if (failFileList && failFileList.length > 0) {
let RecordPath = await this.uploadRecord(arr)
this.$refs.filesTable.clearSelection() this.$refs.filesTable.clearSelection()
failFileList.forEach((row) => { failFileList.forEach((row) => {
row.uploadFileSize = 0 row.uploadFileSize = 0
this.$refs.filesTable.toggleRowSelection(row) this.$refs.filesTable.toggleRowSelection(row)
}) })
this.isFail = true this.isFail = true
this.submitFile(this.successFileList, RecordPath, true)
return false return false
} }
} }
@ -714,7 +721,7 @@ export default {
} }
}, },
// Dicom // Dicom
submitFile(uploadedFileList) { submitFile(uploadedFileList, RecordPath, isReLoad = false) {
if (!this.uploadVisible) return if (!this.uploadVisible) return
this.btnLoading = true this.btnLoading = true
var params = { var params = {
@ -725,9 +732,15 @@ export default {
VisitTaskId: this.currentRow.VisitTaskId, VisitTaskId: this.currentRow.VisitTaskId,
uploadedFileList: uploadedFileList, uploadedFileList: uploadedFileList,
} }
if (RecordPath) {
params.RecordPath = RecordPath.path
params.FailedFileCount = RecordPath.Record.Failed.length
}
uploadNoneDicomFile(params) uploadNoneDicomFile(params)
.then((res) => { .then((res) => {
this.resetFileDiaolg() if (!isReLoad) {
this.resetFileDiaolg()
}
this.getList() this.getList()
// //
this.$emit('getList') this.$emit('getList')
@ -739,6 +752,49 @@ export default {
this.btnLoading = false this.btnLoading = false
}) })
}, },
//
uploadRecord(arr) {
return new Promise(async (resolve) => {
try {
let Record = {
Failed: [],
Existed: [],
Uploaded: [],
FileCount: arr.length,
}
arr.forEach((item) => {
let file = this.fileList.find((data) => data.id === item.id)
if (file.status === 2) {
Record.Uploaded.push(file.curPath)
}
if (file.status === 3) {
Record.Failed.push(file.curPath)
}
})
let text = JSON.stringify(Record)
let logJsonBlob = this.generateTxtFile(text)
let logJsonObjectName = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId}/${this.currentRow.VisitTaskId}/${this.studyMonitorId}.txt`
let logRes
try {
logRes = await this.OSSclient.put(logJsonObjectName, logJsonBlob)
if (logRes && logRes.url) {
resolve({ path: this.$getObjectName(logRes.url), Record })
} else {
resolve(false)
}
} catch (e) {
resolve(false)
}
} catch (err) {
console.log(err)
resolve(false)
}
})
},
generateTxtFile(text) {
let blob = new Blob(['\ufeff', text], { type: 'text/plain' })
return blob
},
}, },
} }
</script> </script>
@ -785,4 +841,12 @@ export default {
pointer-events: none; //pointer-events:none穿 pointer-events: none; //pointer-events:none穿
} }
} }
.tip {
display: flex;
align-items: flex-start;
margin-top: 5px;
i {
margin: 3px 5px 0 0;
}
}
</style> </style>

View File

@ -4,53 +4,74 @@ import store from '@/store'
streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0` streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0`
// 下载文件并压缩 // 下载文件并压缩
function zipFiles(zipName, files) { function zipFiles(zipName, files) {
console.log("同步下载打包开始时间:" + new Date()); return new Promise((resolve) => {
store.dispatch('trials/setUnLock', true) try {
files = formatFiles(files) console.log("同步下载打包开始时间:" + new Date());
// 创建压缩文件输出流 store.dispatch('trials/setUnLock', true)
const zipFileOutputStream = streamSaver.createWriteStream(zipName); files = formatFiles(files)
// 创建下载文件流 // 创建压缩文件输出流
const fileIterator = files.values(); const zipFileOutputStream = streamSaver.createWriteStream(zipName);
const readableZipStream = new ZIP({ // 创建下载文件流
async pull(ctrl) { const fileIterator = files.values();
const fileInfo = fileIterator.next(); const readableZipStream = new ZIP({
if (fileInfo.done) {//迭代终止 async pull(ctrl) {
ctrl.close(); const fileInfo = fileIterator.next();
} else { if (fileInfo.done) {//迭代终止
let { name, url } = fileInfo.value; ctrl.close();
url = decodeUtf8(url); } else {
return fetch(url).then(res => { let { name, url } = fileInfo.value;
ctrl.enqueue({ url = decodeUtf8(url);
name, return fetch(url).then(res => {
stream: () => res.body ctrl.enqueue({
}); name,
}) stream: () => res.body
} });
} })
}); }
if (window.WritableStream && readableZipStream.pipeTo) { }
// 开始下载
readableZipStream
.pipeTo(zipFileOutputStream)
.then(() => {
console.log("同步下载打包结束时间:" + new Date());
store.dispatch('trials/setUnLock', false)
}); });
} if (window.WritableStream && readableZipStream.pipeTo) {
// 开始下载
readableZipStream
.pipeTo(zipFileOutputStream)
.then(() => {
console.log("同步下载打包结束时间:" + new Date());
store.dispatch('trials/setUnLock', false)
resolve(true)
}).catch(err => {
console.log(err);
resolve(false)
});
} else {
resolve(false)
}
} catch (err) {
console.log(err);
resolve(false)
}
})
} }
// 下载文件并修改名称 // 下载文件并修改名称
async function updateFile(file, name) { async function updateFile(file, name) {
try { return new Promise(async resolve => {
store.dispatch('trials/setUnLock', true) try {
const fileOutputStream = streamSaver.createWriteStream(name);
file = decodeUtf8(file);
let res = await fetch(file);
res.body.pipeTo(fileOutputStream).then(() => {
store.dispatch('trials/setUnLock', true) store.dispatch('trials/setUnLock', true)
}); const fileOutputStream = streamSaver.createWriteStream(name);
} catch (err) { file = decodeUtf8(file);
console.log(err) let res = await fetch(file);
} res.body.pipeTo(fileOutputStream).then(() => {
store.dispatch('trials/setUnLock', true)
resolve(true)
}).catch(err => {
console.log(err)
resolve(false)
});
} catch (err) {
console.log(err)
resolve(false)
}
})
} }
// 同名文件修改名称 // 同名文件修改名称
function formatFiles(files) { function formatFiles(files) {
@ -78,8 +99,8 @@ function decodeUtf8(bytes) {
str2.pop(); str2.pop();
return str2.join("/") + '/' + name; return str2.join("/") + '/' + name;
} }
export function downLoadFile(file, name, type = 'file') { export async function downLoadFile(file, name, type = 'file') {
if (type === 'zip') return zipFiles(name, file); if (type === 'zip') return await zipFiles(name, file);
return updateFile(file, name) return await updateFile(file, name)
} }

View File

@ -928,6 +928,7 @@ export default {
let res = await preArchiveStudy({ let res = await preArchiveStudy({
subjectVisitId: this.subjectVisitId, subjectVisitId: this.subjectVisitId,
isDicom: false, isDicom: false,
FileCount: this.selectArr.length,
}) })
if (res.IsSuccess) { if (res.IsSuccess) {
this.studyMonitorId = res.Result this.studyMonitorId = res.Result
@ -952,6 +953,7 @@ export default {
}/${this.$guid()}${file.name }/${this.$guid()}${file.name
.substring(file.name.lastIndexOf('.')) .substring(file.name.lastIndexOf('.'))
.toLocaleLowerCase()}` .toLocaleLowerCase()}`
file.curPath = path
const fileData = await this.fileToBlob(file.file) const fileData = await this.fileToBlob(file.file)
let res = await this.fileToOss(path, fileData, file) let res = await this.fileToOss(path, fileData, file)
if (res) { if (res) {
@ -964,7 +966,8 @@ export default {
}) })
let flag = arr.every((item) => item.status === 2) let flag = arr.every((item) => item.status === 2)
if (flag) { if (flag) {
return this.submitFile(this.successFileList) let RecordPath = await this.uploadRecord(arr)
return this.submitFile(this.successFileList, RecordPath)
} }
} else { } else {
file.status = 3 file.status = 3
@ -973,12 +976,14 @@ export default {
if (flag) { if (flag) {
let failFileList = arr.filter((item) => item.status === 3) let failFileList = arr.filter((item) => item.status === 3)
if (failFileList && failFileList.length > 0) { if (failFileList && failFileList.length > 0) {
let RecordPath = await this.uploadRecord(arr)
this.$refs.filesTable.clearSelection() this.$refs.filesTable.clearSelection()
failFileList.forEach((row) => { failFileList.forEach((row) => {
row.uploadFileSize = 0 row.uploadFileSize = 0
this.$refs.filesTable.toggleRowSelection(row) this.$refs.filesTable.toggleRowSelection(row)
}) })
this.isFail = true this.isFail = true
this.submitFile(this.successFileList, RecordPath, true)
return false return false
} }
} }
@ -1016,7 +1021,7 @@ export default {
} }
}, },
// Dicom // Dicom
submitFile(uploadedFileList) { submitFile(uploadedFileList, RecordPath, isReLoad = false) {
if (!this.uploadVisible) return if (!this.uploadVisible) return
this.btnLoading = true this.btnLoading = true
var params = { var params = {
@ -1026,9 +1031,15 @@ export default {
studyMonitorId: this.studyMonitorId, studyMonitorId: this.studyMonitorId,
uploadedFileList: uploadedFileList, uploadedFileList: uploadedFileList,
} }
if (RecordPath) {
params.RecordPath = RecordPath.path
params.FailedFileCount = RecordPath.Record.Failed.length
}
uploadNoneDicomFile(params) uploadNoneDicomFile(params)
.then((res) => { .then((res) => {
this.resetFileDiaolg() if (!isReLoad) {
this.resetFileDiaolg()
}
this.getNoneDicomList() this.getNoneDicomList()
// //
this.$emit('getList') this.$emit('getList')
@ -1040,6 +1051,49 @@ export default {
this.btnLoading = false this.btnLoading = false
}) })
}, },
//
uploadRecord(arr) {
return new Promise(async (resolve) => {
try {
let Record = {
Failed: [],
Existed: [],
Uploaded: [],
FileCount: arr.length,
}
arr.forEach((item) => {
let file = this.fileList.find((data) => data.id === item.id)
if (file.status === 2) {
Record.Uploaded.push(file.curPath)
}
if (file.status === 3) {
Record.Failed.push(file.curPath)
}
})
let text = JSON.stringify(Record)
let logJsonBlob = this.generateTxtFile(text)
let logJsonObjectName = `/${this.trialId}/Image/${this.data.SubjectId}/${this.data.Id}/${this.studyMonitorId}.txt`
let logRes
try {
logRes = await this.OSSclient.put(logJsonObjectName, logJsonBlob)
if (logRes && logRes.url) {
resolve({ path: this.$getObjectName(logRes.url), Record })
} else {
resolve(false)
}
} catch (e) {
resolve(false)
}
} catch (err) {
console.log(err)
resolve(false)
}
})
},
generateTxtFile(text) {
let blob = new Blob(['\ufeff', text], { type: 'text/plain' })
return blob
},
resetFileDiaolg() { resetFileDiaolg() {
this.btnLoading = false this.btnLoading = false
this.uploadVisible = false this.uploadVisible = false

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,13 @@
> >
{{ $store.state.trials.uploadTip }} {{ $store.state.trials.uploadTip }}
</div> --> </div> -->
<el-tooltip
:content="$t('trials:download:tip:message')"
placement="top-end"
effect="light"
>
<i class="el-icon-warning-outline" style="font-size: 18px"></i>
</el-tooltip>
<!-- 下载所有影像 --> <!-- 下载所有影像 -->
<el-button <el-button
v-if=" v-if="
@ -317,6 +324,13 @@
> >
{{ $store.state.trials.uploadTip }} {{ $store.state.trials.uploadTip }}
</div> --> </div> -->
<el-tooltip
:content="$t('trials:download:tip:message')"
placement="top-end"
effect="light"
>
<i class="el-icon-warning-outline" style="font-size: 18px"></i>
</el-tooltip>
<!-- 下载所有影像 --> <!-- 下载所有影像 -->
<el-button <el-button
v-if=" v-if="
@ -1667,7 +1681,9 @@ export default {
if (item.actionContent) { if (item.actionContent) {
// //
actions.push(`${item.actionContent}`) actions.push(`${item.actionContent}`)
str = `${str}${this.$t('trials:audit:form:actionMatters')}<br><div style='margin-left:20px'>${item.actionContent}</div>` str = `${str}${this.$t(
'trials:audit:form:actionMatters'
)}<br><div style='margin-left:20px'>${item.actionContent}</div>`
} }
contents.push(str) contents.push(str)
} }