diff --git a/package.json b/package.json index 1887aa91..adbd5052 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "axios": "0.18.1", "babel-eslint": "7.2.3", "copy-webpack-plugin": "^4.5.2", + "@aws-sdk/client-s3": "^3.370.0", "core-js": "^3.8.3", "cornerstone-core": "^2.6.1", "cornerstone-math": "^0.1.10", diff --git a/src/store/modules/trials.js b/src/store/modules/trials.js index b66e3bd5..0422295e 100644 --- a/src/store/modules/trials.js +++ b/src/store/modules/trials.js @@ -9,7 +9,7 @@ const getDefaultState = () => { studyListQuery: null, unlock: false, config: {}, - uploadTip: null, + uploadTip: '0.00kb/s', timer: null, whiteList: [], checkTaskId: null diff --git a/src/utils/dcmUpload/dcmUpload.js b/src/utils/dcmUpload/dcmUpload.js index 56ab4599..9230c62d 100644 --- a/src/utils/dcmUpload/dcmUpload.js +++ b/src/utils/dcmUpload/dcmUpload.js @@ -1,14 +1,14 @@ import Vue from 'vue' import { anonymization } from './anonymization' -export const dcmUpload = async function (name, file, config) { +export const dcmUpload = async function (data, config, progressFn) { return new Promise(async resolve => { try { // let blob = await encoder(file, config) - let blob = await fileToBlob(file) + let blob = await fileToBlob(data.file) if (config) { - blob = await anonymization(file, config) + blob = await anonymization(data.file, config) } - let res = await Vue.prototype.OSSclient.put(name, blob.blob) + let res = await Vue.prototype.OSSclient.multipartUpload(Object.assign(data, { file: blob.blob }), progressFn) resolve({ ...res, image: blob.pixelDataElement @@ -19,7 +19,7 @@ export const dcmUpload = async function (name, file, config) { } catch (e) { - console.log(file, 'warning') + console.log(data.file, 'warning') resolve(false) console.log(e) } diff --git a/src/utils/multipartUpload/aws.js b/src/utils/multipartUpload/aws.js new file mode 100644 index 00000000..7e61c7bc --- /dev/null +++ b/src/utils/multipartUpload/aws.js @@ -0,0 +1,457 @@ +const { + CreateMultipartUploadCommand, + UploadPartCommand, + CompleteMultipartUploadCommand, + ListMultipartUploadsCommand,//bucket中正在上传的文件列表 + ListPartsCommand,//列出文件已上传的分片 + GetObjectCommand,//获取文件 +} = require("@aws-sdk/client-s3"); +import SparkMD5 from "./spark-md5.min.js"; +import store from "@/store"; +let timer = null, // 网速定时器 + bytesReceivedPerSecond = {}; // 时间节点上传文件总量 +export function AWSclose() { + if (timer) { + clearInterval(timer); + } + bytesReceivedPerSecond = {}; +} +//查询文件是否存在于bucket或者正在上传 +export async function exist(s3, bucket, fileInformation, progressFn, changeStatus) { + // 拿到上传到的file + const File = fileInformation.file; + // 拿到上传的size + const uploadFileSize = File.size; // 这里拿到的单位是字节(uploadFileSize/ 1024 / 1024 + // = 多少兆) + // 设置每一片的大小,shardSize 指定上传的每个分片的大小,范围为100 KB~5 GB。 + // 分片标准为5MB,文件总大小大于5GB分片为20MB + let shardSize = 5 * 1024 * 1024; + if (uploadFileSize < partSize) { + shardSize = uploadFileSize; + } + if (uploadFileSize > 5 * 1024 * 1024 * 1024) { + shardSize = 20 * 1024 * 1024; + } + fileInformation = Object.assign({ + shardSize, + sharding: [] + }, fileInformation) + if (fileInformation.speed) { + setTimer(); + } + // 1、查询该文件是否已上传到bucket + //判断sharding里面是否有东西,有东西证明已经上传过分片了,不需要再进行检测 + if (fileInformation.sharding.length === 0) { + let existBucket = await existInBucket({ s3, bucket, fileInformation: fileInformation }); + console.log("existBucket", existBucket) + if (existBucket === 'true') { + changeStatus(fileInformation.path, 'success');//直接告诉前端,状态 + return; + } else if (existBucket === 'same key') { + console.log(fileInformation.path + " bucket中存在同名不同内容的文件"); + } else if (existBucket === 'not exist') { + console.log(fileInformation.path + " bucket中不存在该文件"); + } + //2、查询该文件是否存在上传事件 + let upload = await existUpload({ s3, bucket: bucket, fileInformation: fileInformation }); + if (upload.code === 0) { + //存在该上传事件并且已经上传了多个分片 + console.log(fileInformation.path + " 存在上传事件,并已经上传多个分片"); + //将分片存入sharding + const uploadId = upload.uploadId; + let parts = upload.parts; + let SIZE = 0; + for (let i = 0; i < parts.length; i++) { + SIZE += parts[i].Size; + fileInformation.sharding.push({ ETag: parts[i].ETag, PartNumber: parts[i].PartNumber, Size: parts[i].Size, UploadId: uploadId }); + } + progressFn(SIZE / uploadFileSize, { fileSize: uploadFileSize }, 0);//告诉前端,加入分片 + //重新上传 + await uploadFile({ fileInformation: fileInformation, uploadId: uploadId, bucket, changeStatus, getSuspend, progressFn }); + } else if (upload.code === 1) { + // //重名但是不同文件 + console.log('err 重名文件') + changeStatus(fileInformation.path, 'same key'); + } else if (upload.code === 2) { + //没有上传事件 + console.log(fileInformation.path + " 不存在上传事件"); + //建立分段上传事件 + const connect = await createMultipartUpload({ s3, bucket: bucket, key: fileInformation.path, type: fileInformation.file.type }); + //上传整个文件 + await uploadFile({ s3, fileInformation: fileInformation, uploadId: connect.UploadId, bucket: bucket, changeStatus, progressFn }); + } + } else { + //分片组里面有东西 + //重新上传 + await uploadFile({ s3, fileInformation: fileInformation, uploadId: fileInformation.sharding[0].UploadId, bucket, changeStatus, progressFn }); + } +} + +//上传文件未上传的所有分片 +async function uploadFile({ s3, fileInformation, uploadId, bucket, changeStatus, progressFn }) {// file:上传文件, uploadId parts:已上传的分片 + const chunkCount = Math.ceil(fileInformation.file.size / fileInformation.shardSize)//总分片数 + //循环切片并上传 + for (let i = 0; i < chunkCount; i++) { + let start = i * fileInformation.shardSize;//文件分片开始位置 + let end = Math.min(fileInformation.file.size, start + fileInformation.shardSize)//文件分片结束位置 + let _chunkFile = fileInformation.file.slice(start, end);//切片文件 即 待上传文件分片 + //判断parts中是否存在该分片 + let res1 = fileInformation.sharding.filter((part) => { + return part.PartNumber === (i + 1); + }); + if (res1.length === 0) { + //不包含该分片 + const upload = await uploadPart({ s3, f: _chunkFile, uploadId: uploadId, key: fileInformation.path, bucket: bucket, num: i + 1 });//将分片上传 + //判断sharding中是否存在该分片,如果不存在的话,才判错 + let res2 = fileInformation.sharding.filter((part) => { + return part.PartNumber === (i + 1); + }); + if (res2.length === 0) { + if (upload !== 'err') {//上传分片成功,并且没有暂停上传 + //判断是否存在该分片 + //判断parts中是否存在该分片 + let res3 = fileInformation.sharding.filter((part) => { + return part.PartNumber === (i + 1); + }); + if (res3.length === 0) { + let LASTSIZE = fileInformation.sharding.reduce((sum, item) => sum + item.Size, 0) + fileInformation.sharding.push({ ETag: upload.ETag, PartNumber: i + 1, Size: _chunkFile.size, UploadId: uploadId });//上传成功,存到sharding + let SIZE = fileInformation.sharding.reduce((sum, item) => sum + item.Size, 0) + let lastPercentage = LASTSIZE / fileInformation.file.size, percentage = SIZE / fileInformation.file.size; + progressFn(percentage, fileInformation.file, lastPercentage); + if (fileInformation.speed) { + let time = new Date().getTime(); + let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b); + let bytesTime = timeList.find(item => time - item < 1000); + if (bytesTime) { + bytesReceivedPerSecond[bytesTime] += fileInformation.file.size * percentage; + } else { + console.log("未查询到时间") + if (timeList.length > 0) { + bytesReceivedPerSecond[timeList[timeList.length - 1]] += fileInformation.file.size * percentage; + } else { + bytesReceivedPerSecond[time] = fileInformation.file.size * percentage; + } + } + } + } + } else if (upload === 'err') { + changeStatus(fileInformation.path, 'err'); + return; + } + } + + } + }//for + if (fileInformation.sharding.length === chunkCount) { + //合并分片 + const complete = await completeMultipartUpload({ s3, bucket: bucket, key: fileInformation.path, sharding: fileInformation.sharding, uploadId: uploadId }); + if (complete !== 'err') { + changeStatus(fileInformation.path, 'success');//通知前端,上传成功 + } else { + changeStatus(fileInformation.path, 'err');//通知前端,上传失败 + } + + } +} + +// 判断该文件是否已经存在于bucket +// bucket file:上传文件 +// 返回值 'same key':同名不同文件 'not exist':不存在该文件 'true':该文件已存在bucket中 +async function existInBucket({ s3, bucket, fileInformation }) { + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + //getObject 每次最多传回767448b的数据,所以要分段请求 + let bucketFileUniArray = []; + // 分段 + let count = Math.ceil(fileInformation.file.size / 767448); + if (count > 4) { + count = 4; + } + for (let i = 0; i < count; i++) { + const obj = await getObject({ s3, bucket: bucket, fileInformation: fileInformation, count: i }); + if (obj !== 'err') { + //获取文件的文件体 计算某个分片的md5 + const fileBody = obj.Body; + let fileUnitArray = await fileBody.transformToByteArray(); + bucketFileUniArray = [...bucketFileUniArray, ...fileUnitArray]; + } else { + return 'not exist'; + } + } + let bucketFileBufferArray = new Uint8Array(bucketFileUniArray); + console.log("bucketFileBufferArray.buffer", bucketFileBufferArray.buffer) + // 将传入文件的fileReader 转成 arrayBuffer + let fileArrayBuff = null; + fileArrayBuff = await new Promise((resolve) => { + let fileReader = new FileReader(); + fileReader.readAsArrayBuffer(fileInformation.file.slice(0, count * 767448)); + fileReader.onload = (e) => { + resolve(e.target.result); + }; + }); + if (fileArrayBuff.byteLength > count * 767448) { + fileArrayBuff = fileArrayBuff.slice(0, count * 767448); + } + let bodyMD5 = await getMD5({ arrayBuffer: bucketFileBufferArray.buffer }); + let fileMD5 = await getMD5({ arrayBuffer: fileArrayBuff }); + if (bodyMD5 === fileMD5) { + //证明是同一个文件 秒传 + return 'true'; + } else { + return 'same key'; + } +} + +//判断该文件是否正在上传 +// bucket:bucket file:上传文件 +//返回值 'not exist upload':不存在上传事件 'same key':同名不同文件 +async function existUpload({ s3, bucket, fileInformation }) { + //判断该文件是否有上传事件 + const listUploads = await listMultipartUploadsCommand({ s3, bucket: bucket, key: fileInformation.path }); + if (listUploads !== 'err') { + if (listUploads.Uploads !== undefined && listUploads.Uploads.length > 0) { + //存在上传事件 获取上传的第一个分片的eTag,计算传入文件md5,相比较是否相同 + const uploads = listUploads.Uploads; + for (const one in uploads) {//可能存在多个连接 + let uploadOne = uploads[one]; + const uploadId = uploadOne.UploadId;//UploadId + const key = uploadOne.Key;//key + //查询该文件已上传分片 + const listParts = await listPartsCommand({ s3, bucket: bucket, key: key, uploadId: uploadId }); + if (listParts !== 'err') { + if (listParts.Parts !== undefined && listParts.Parts.length !== 0) { + //存在分片 + let etag = listParts.Parts[0].ETag; + //计算文件的第一个分片的md5 + let fileSlice = null; + if (fileInformation.file.size > fileInformation.shardSize) { + fileSlice = fileInformation.file.slice(0, fileInformation.shardSize); + } else { + fileSlice = fileInformation.file; + } + let fileMD5 = await new Promise((resolve) => { + const fileReader = new FileReader(); + var spark = new SparkMD5.ArrayBuffer(); + fileReader.readAsArrayBuffer(fileSlice); + fileReader.onload = (e) => { + spark.append(e.target.result); + var m = spark.end(); + resolve(m); + }; + }); + if (etag.split('"')[1] === fileMD5) { + //是同一个文件上传 + return { + code: 0, + message: 'true', + uploadId: uploadId, + key: key, + parts: listParts.Parts + } + } else { + //同名不同文件 + continue; + } + } else { + //该文件有进行上传,但没有上传完成一个分片 + continue; + } + } else { + //有连接,没上传分片 + continue; + } + }//for + return { + code: 1, + message: 'same key' + } + } else { + //无连接 + return { + code: 2, + message: 'not exist upload' + }; + } + } else { + //无连接 + return { + code: 2, + message: 'not exist upload' + }; + } +} + +//计算arrayBuffer的md5值 +async function getMD5({ arrayBuffer }) { + console.log("arrayBuffer", arrayBuffer) + return await new Promise((resolve) => { + const spark = new SparkMD5.ArrayBuffer(); + spark.append(arrayBuffer); + const m = spark.end(); + resolve(m); + }); +} + +//建立文件上传事件 +async function createMultipartUpload({ s3, bucket, key, type }) {//bucket:bucket key:文件名 type:文件类型 + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + const params = { + Bucket: bucket, + Key: key, + ContentType: type + }; + const res = async () => { + try { + return await s3.send(new CreateMultipartUploadCommand(params)); + } catch (err) { + console.log('建立上传事件失败:', err.message) + return 'err'; + } + } + return res(); +} + +//上传一个分片 +async function uploadPart({ s3, f, uploadId, key, bucket, num }) { //f:文件分片,num:分片标号 + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + const params = { + Bucket: bucket, + Key: key, + PartNumber: num, + UploadId: uploadId, + Body: f, + // ContentDisposition: "attachment; filename=hahaha.dcm" + }; + const res = async () => { + try { + return await s3.send(new UploadPartCommand(params)); + } catch (err) { + console.log('上传分片第 ' + num + ' 片错误信息', err.message) + return 'err'; + } + } + return res(); +} +//将分片合并 +async function completeMultipartUpload({ s3, bucket, key, sharding, uploadId }) { + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + let parts = []; + for (let i = 0; i < sharding.length; i++) { + parts.push({ + "ETag": sharding[i].ETag, + "PartNumber": sharding[i].PartNumber, + }) + } + const params = { + Bucket: bucket, + Key: key, + MultipartUpload: { + Parts: parts + }, + UploadId: uploadId + }; + const res = async () => { + try { + return await s3.send(new CompleteMultipartUploadCommand(params)) + } catch (err) { + console.log("合并分片失败: ", err.message); + return 'err'; + } + } + return res(); +} + +//查询某个文件已经上传的所有分片 +async function listPartsCommand({ s3, bucket, key, uploadId }) { + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + const params = { + Bucket: bucket, + Key: key, + UploadId: uploadId + }; + const res = async () => { + try { + return await s3.send(new ListPartsCommand(params)); + } catch (err) { + console.log("查询该文件已上传分片失败: " + err.message); + return 'err'; + } + } + return res(); +} +//查询该文件是否存在上传事件 +async function listMultipartUploadsCommand({ s3, bucket, key }) { + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + const params = { + Bucket: bucket, + Delimiter: '', + MaxUploads: 1000, + Prefix: key + }; + const res = async () => { + try { + return await s3.send(new ListMultipartUploadsCommand(params)); + } catch (err) { + console.log("查询 " + key + " 文件是否存在上传事件失败: " + err.message); + return 'err'; + } + } + return res(); +} +//获取文件 +async function getObject({ s3, bucket, fileInformation, count }) { + //一次请求最多 767448 + if (s3 === null) { + return console.log("未创建s3客户端,请先调用init事件"); + } + let byte1 = ((count + 1) * 767448 - 1) > fileInformation.file.size ? fileInformation.file.size : ((count + 1) * 767448 - 1); + let byte2 = (count * 767448) > fileInformation.file.size ? fileInformation.file.size : (count * 767448); + let range = "bytes=" + byte2 + "-" + byte1; + const params = { + Bucket: bucket, + Key: fileInformation.path, + Range: range + }; + const res = async () => { + try { + return await s3.send(new GetObjectCommand(params)); + } catch (err) { + console.log('获取 ' + fileInformation.path + ' 文件失败:', err.message); + return 'err'; + } + } + return res(); +} +function setTimer() { + if (timer) return false; + timer = setInterval(() => { + let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b); + if (timeList.length > 0) { + let totalBytes = timeList.reduce((sum, bytes) => sum + bytesReceivedPerSecond[bytes], 0) / (5 * 1024); + let unit = 'kb/s'; + if (totalBytes > 1024) { + totalBytes = totalBytes / 1024; + unit = "mb/s"; + } + store.state.trials.uploadTip = totalBytes.toFixed(2) + unit; + } + if (timeList.length >= 5) { + delete bytesReceivedPerSecond[timeList[0]] + } + let time = new Date().getTime(); + bytesReceivedPerSecond[time] = 0; + }, 1000) +} + diff --git a/src/utils/multipartUpload/oss.js b/src/utils/multipartUpload/oss.js new file mode 100644 index 00000000..ac718b8a --- /dev/null +++ b/src/utils/multipartUpload/oss.js @@ -0,0 +1,153 @@ +import moment from "moment"; +import store from "@/store"; +let savaData = {}, + checkData = {}, // 当前上传的节点文件和上一次提交进度 + timer = null, // 网速定时器 + bytesReceivedPerSecond = {}; // 时间节点上传文件总量 +export function OSSclose() { + if (timer) { + clearInterval(timer); + } + bytesReceivedPerSecond = {}; + savaData = {}; + checkData = {}; + saveFinishedData(savaData); +} +export async function customerHttp(OSSclient, data, progressFn) { + // 拿到上传到的file + const uploadFile = data.file; + // 拿到上传的size + const uploadFileSize = uploadFile.size; // 这里拿到的单位是字节(uploadFileSize/ 1024 / 1024 + // = 多少兆) + // 设置每一片的大小,partSize 指定上传的每个分片的大小,范围为100 KB~5 GB。 + // 分片标准为5MB,文件总大小大于5GB分片为20MB + let partSize = 5 * 1024 * 1024; + if (uploadFileSize < partSize) { + partSize = uploadFileSize; + } + if (uploadFileSize > 5 * 1024 * 1024 * 1024) { + partSize = 20 * 1024 * 1024; + } + // 设置所有的文件上传所有的唯一的saveFileId + const saveFileId = `${uploadFileSize}_${data.path}`; + if (data.speed) { + setTimer(); + } + initPage(); + let res = await multipartUpload(OSSclient, partSize, saveFileId, uploadFile, data, progressFn); + return res; +} + +async function multipartUpload(OSSclient, partSize, saveFileId, uploadFile, data, progressFn) { + try { + // object-name目前我是用的uploadFile.name,其实也是要根据你们的项目而定, + // 有没有具体的规定, 要不要加项目名, 要不要加对应的环境; + // 上传的参数 + const uploadParams = { + partSize, + progress: (percentage, checkpoint) => { + savaData[saveFileId] = checkpoint; + if (!checkData[saveFileId]) { + checkData[saveFileId] = 0 + } + if (data.speed) { + let time = new Date().getTime(); + let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b); + let bytesTime = timeList.find(item => time - item < 1000); + if (bytesTime) { + bytesReceivedPerSecond[bytesTime] += data.file.size * percentage; + } else { + console.log("未查询到时间") + if (timeList.length > 0) { + bytesReceivedPerSecond[timeList[timeList.length - 1]] += data.file.size * percentage; + } else { + bytesReceivedPerSecond[time] = data.file.size * percentage; + } + } + } + savaData["lastSaveTime"] = new Date(); + progressFn(percentage, data.file, checkData[saveFileId]) + checkData[saveFileId] = percentage; + if (percentage === 1) { + delete checkData[saveFileId] + } + // 在上传过程中,把已经上传的数据存储下来 + saveFinishedData(savaData); + }, + // headers: { + // "Content-Disposition": `attachment; filename=hahaha.dcm`, + // "Cache-Control": "public, no-cache" + // } + }; + // 断点续传 + await resumeUpload(uploadParams, saveFileId); + const res = await OSSclient.multipartUpload( + data.path, + uploadFile, + uploadParams + ); + if (res.res.status === 200) { + // 重新去掉某个缓存进行设置 + delete savaData[saveFileId]; + saveFinishedData(savaData); + } + return res; + } catch (e) { + console.log(e); + // 捕获超时异常。 + if (e.code === "ConnectionTimeoutError") { + console.log("TimeoutError"); + // do ConnectionTimeoutError operation + } + return false; + } +} +async function resumeUpload(uploadParams, saveFileId) { + if (localStorage.getItem("upload-function-name")) { + const obj = JSON.parse(localStorage.getItem("upload-function-name")); + if (Object.keys(obj).includes(saveFileId)) { + uploadParams.checkpoint = obj[saveFileId]; + } + } +} +// 存储到内存 +function saveFinishedData(finishedData) { + localStorage.setItem( + "upload-function-name", + JSON.stringify(finishedData) + ); +} +function initPage() { + // 判断是不是有缓存 + const localData = localStorage.getItem("upload-function-name"); + if (!localData) return; + savaData = JSON.parse(localData); + // 当前时间 > 存储时间(1000 * 60 * 60表示1h,意思就是这些数据你要存多久, + // 可以是1h也可以是多少天,随意) + if ( + moment(new Date()).diff(moment(savaData.lastSaveTime)) > + 1000 * 60 * 60 + ) { + localStorage.removeItem("upload-function-name"); + } +} +function setTimer() { + if (timer) return false; + timer = setInterval(() => { + let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b); + if (timeList.length > 0) { + let totalBytes = timeList.reduce((sum, bytes) => sum + bytesReceivedPerSecond[bytes], 0) / (5 * 1024); + let unit = 'kb/s'; + if (totalBytes > 1024) { + totalBytes = totalBytes / 1024; + unit = "mb/s"; + } + store.state.trials.uploadTip = totalBytes.toFixed(2) + unit; + } + if (timeList.length >= 5) { + delete bytesReceivedPerSecond[timeList[0]] + } + let time = new Date().getTime(); + bytesReceivedPerSecond[time] = 0; + }, 1000) +} \ No newline at end of file diff --git a/src/utils/multipartUpload/spark-md5.min.js b/src/utils/multipartUpload/spark-md5.min.js new file mode 100644 index 00000000..2ef527dd --- /dev/null +++ b/src/utils/multipartUpload/spark-md5.min.js @@ -0,0 +1 @@ +(function(factory){if(typeof exports==="object"){module.exports=factory()}else if(typeof define==="function"&&define.amd){define(factory)}else{var glob;try{glob=window}catch(e){glob=self}glob.SparkMD5=factory()}})(function(undefined){"use strict";var add32=function(a,b){return a+b&4294967295},hex_chr=["0","1","2","3","4","5","6","7","8","9","a","b","c","d","e","f"];function cmn(q,a,b,x,s,t){a=add32(add32(a,q),add32(x,t));return add32(a<>>32-s,b)}function md5cycle(x,k){var a=x[0],b=x[1],c=x[2],d=x[3];a+=(b&c|~b&d)+k[0]-680876936|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[1]-389564586|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[2]+606105819|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[3]-1044525330|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[4]-176418897|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[5]+1200080426|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[6]-1473231341|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[7]-45705983|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[8]+1770035416|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[9]-1958414417|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[10]-42063|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[11]-1990404162|0;b=(b<<22|b>>>10)+c|0;a+=(b&c|~b&d)+k[12]+1804603682|0;a=(a<<7|a>>>25)+b|0;d+=(a&b|~a&c)+k[13]-40341101|0;d=(d<<12|d>>>20)+a|0;c+=(d&a|~d&b)+k[14]-1502002290|0;c=(c<<17|c>>>15)+d|0;b+=(c&d|~c&a)+k[15]+1236535329|0;b=(b<<22|b>>>10)+c|0;a+=(b&d|c&~d)+k[1]-165796510|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[6]-1069501632|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[11]+643717713|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[0]-373897302|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[5]-701558691|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[10]+38016083|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[15]-660478335|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[4]-405537848|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[9]+568446438|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[14]-1019803690|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[3]-187363961|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[8]+1163531501|0;b=(b<<20|b>>>12)+c|0;a+=(b&d|c&~d)+k[13]-1444681467|0;a=(a<<5|a>>>27)+b|0;d+=(a&c|b&~c)+k[2]-51403784|0;d=(d<<9|d>>>23)+a|0;c+=(d&b|a&~b)+k[7]+1735328473|0;c=(c<<14|c>>>18)+d|0;b+=(c&a|d&~a)+k[12]-1926607734|0;b=(b<<20|b>>>12)+c|0;a+=(b^c^d)+k[5]-378558|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[8]-2022574463|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[11]+1839030562|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[14]-35309556|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[1]-1530992060|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[4]+1272893353|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[7]-155497632|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[10]-1094730640|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[13]+681279174|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[0]-358537222|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[3]-722521979|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[6]+76029189|0;b=(b<<23|b>>>9)+c|0;a+=(b^c^d)+k[9]-640364487|0;a=(a<<4|a>>>28)+b|0;d+=(a^b^c)+k[12]-421815835|0;d=(d<<11|d>>>21)+a|0;c+=(d^a^b)+k[15]+530742520|0;c=(c<<16|c>>>16)+d|0;b+=(c^d^a)+k[2]-995338651|0;b=(b<<23|b>>>9)+c|0;a+=(c^(b|~d))+k[0]-198630844|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[7]+1126891415|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[14]-1416354905|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[5]-57434055|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[12]+1700485571|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[3]-1894986606|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[10]-1051523|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[1]-2054922799|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[8]+1873313359|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[15]-30611744|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[6]-1560198380|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[13]+1309151649|0;b=(b<<21|b>>>11)+c|0;a+=(c^(b|~d))+k[4]-145523070|0;a=(a<<6|a>>>26)+b|0;d+=(b^(a|~c))+k[11]-1120210379|0;d=(d<<10|d>>>22)+a|0;c+=(a^(d|~b))+k[2]+718787259|0;c=(c<<15|c>>>17)+d|0;b+=(d^(c|~a))+k[9]-343485551|0;b=(b<<21|b>>>11)+c|0;x[0]=a+x[0]|0;x[1]=b+x[1]|0;x[2]=c+x[2]|0;x[3]=d+x[3]|0}function md5blk(s){var md5blks=[],i;for(i=0;i<64;i+=4){md5blks[i>>2]=s.charCodeAt(i)+(s.charCodeAt(i+1)<<8)+(s.charCodeAt(i+2)<<16)+(s.charCodeAt(i+3)<<24)}return md5blks}function md5blk_array(a){var md5blks=[],i;for(i=0;i<64;i+=4){md5blks[i>>2]=a[i]+(a[i+1]<<8)+(a[i+2]<<16)+(a[i+3]<<24)}return md5blks}function md51(s){var n=s.length,state=[1732584193,-271733879,-1732584194,271733878],i,length,tail,tmp,lo,hi;for(i=64;i<=n;i+=64){md5cycle(state,md5blk(s.substring(i-64,i)))}s=s.substring(i-64);length=s.length;tail=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0];for(i=0;i>2]|=s.charCodeAt(i)<<(i%4<<3)}tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(state,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=n*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(state,tail);return state}function md51_array(a){var n=a.length,state=[1732584193,-271733879,-1732584194,271733878],i,length,tail,tmp,lo,hi;for(i=64;i<=n;i+=64){md5cycle(state,md5blk_array(a.subarray(i-64,i)))}a=i-64>2]|=a[i]<<(i%4<<3)}tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(state,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=n*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(state,tail);return state}function rhex(n){var s="",j;for(j=0;j<4;j+=1){s+=hex_chr[n>>j*8+4&15]+hex_chr[n>>j*8&15]}return s}function hex(x){var i;for(i=0;i>16)+(y>>16)+(lsw>>16);return msw<<16|lsw&65535}}if(typeof ArrayBuffer!=="undefined"&&!ArrayBuffer.prototype.slice){(function(){function clamp(val,length){val=val|0||0;if(val<0){return Math.max(val+length,0)}return Math.min(val,length)}ArrayBuffer.prototype.slice=function(from,to){var length=this.byteLength,begin=clamp(from,length),end=length,num,target,targetArray,sourceArray;if(to!==undefined){end=clamp(to,length)}if(begin>end){return new ArrayBuffer(0)}num=end-begin;target=new ArrayBuffer(num);targetArray=new Uint8Array(target);sourceArray=new Uint8Array(this,begin,num);targetArray.set(sourceArray);return target}})()}function toUtf8(str){if(/[\u0080-\uFFFF]/.test(str)){str=unescape(encodeURIComponent(str))}return str}function utf8Str2ArrayBuffer(str,returnUInt8Array){var length=str.length,buff=new ArrayBuffer(length),arr=new Uint8Array(buff),i;for(i=0;i>2]|=buff.charCodeAt(i)<<(i%4<<3)}this._finish(tail,length);ret=hex(this._hash);if(raw){ret=hexToBinaryString(ret)}this.reset();return ret};SparkMD5.prototype.reset=function(){this._buff="";this._length=0;this._hash=[1732584193,-271733879,-1732584194,271733878];return this};SparkMD5.prototype.getState=function(){return{buff:this._buff,length:this._length,hash:this._hash.slice()}};SparkMD5.prototype.setState=function(state){this._buff=state.buff;this._length=state.length;this._hash=state.hash;return this};SparkMD5.prototype.destroy=function(){delete this._hash;delete this._buff;delete this._length};SparkMD5.prototype._finish=function(tail,length){var i=length,tmp,lo,hi;tail[i>>2]|=128<<(i%4<<3);if(i>55){md5cycle(this._hash,tail);for(i=0;i<16;i+=1){tail[i]=0}}tmp=this._length*8;tmp=tmp.toString(16).match(/(.*?)(.{0,8})$/);lo=parseInt(tmp[2],16);hi=parseInt(tmp[1],16)||0;tail[14]=lo;tail[15]=hi;md5cycle(this._hash,tail)};SparkMD5.hash=function(str,raw){return SparkMD5.hashBinary(toUtf8(str),raw)};SparkMD5.hashBinary=function(content,raw){var hash=md51(content),ret=hex(hash);return raw?hexToBinaryString(ret):ret};SparkMD5.ArrayBuffer=function(){this.reset()};SparkMD5.ArrayBuffer.prototype.append=function(arr){var buff=concatenateArrayBuffers(this._buff.buffer,arr,true),length=buff.length,i;this._length+=arr.byteLength;for(i=64;i<=length;i+=64){md5cycle(this._hash,md5blk_array(buff.subarray(i-64,i)))}this._buff=i-64>2]|=buff[i]<<(i%4<<3)}this._finish(tail,length);ret=hex(this._hash);if(raw){ret=hexToBinaryString(ret)}this.reset();return ret};SparkMD5.ArrayBuffer.prototype.reset=function(){this._buff=new Uint8Array(0);this._length=0;this._hash=[1732584193,-271733879,-1732584194,271733878];return this};SparkMD5.ArrayBuffer.prototype.getState=function(){var state=SparkMD5.prototype.getState.call(this);state.buff=arrayBuffer2Utf8Str(state.buff);return state};SparkMD5.ArrayBuffer.prototype.setState=function(state){state.buff=utf8Str2ArrayBuffer(state.buff,true);return SparkMD5.prototype.setState.call(this,state)};SparkMD5.ArrayBuffer.prototype.destroy=SparkMD5.prototype.destroy;SparkMD5.ArrayBuffer.prototype._finish=SparkMD5.prototype._finish;SparkMD5.ArrayBuffer.hash=function(arr,raw){var hash=md51_array(new Uint8Array(arr)),ret=hex(hash);return raw?hexToBinaryString(ret):ret};return SparkMD5}); diff --git a/src/utils/oss.js b/src/utils/oss.js index 742d587d..72766652 100644 --- a/src/utils/oss.js +++ b/src/utils/oss.js @@ -3,17 +3,16 @@ const router = require('@/router'); const Minio = require('minio') const stream = require('stream') import Vue from 'vue' +import { customerHttp, OSSclose } from "@/utils/multipartUpload/oss" +import { exist, AWSclose } from "@/utils/multipartUpload/aws" const { GetObjectStoreToken } = require('../api/user.js') +const { + S3Client, +} = require("@aws-sdk/client-s3"); Vue.prototype.OSSclientConfig = { } -function blobToBuffer(blob, fileName) { - return new Promise((resolve, reject) => { - const file = new File([blob], fileName); - resolve(file) - }) -} async function ossGenerateSTS() { let res = await GetObjectStoreToken() @@ -29,6 +28,16 @@ async function ossGenerateSTS() { put: function (objectName, object) { return new Promise(async (resolve, reject) => { try { + let config = await getSTSToken(Vue.prototype.OSSclientConfig.Expiration); + if (config) { + Vue.prototype.OSSclientConfig = { ...config.Result[res.Result.ObjectStoreUse] } + Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse; + Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint; + Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName + Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken + Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000 + OSSclient = new OSS(Vue.prototype.OSSclientConfig); + } let _vm = router.default.app if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { var objectItem = objectName.split('/') @@ -49,6 +58,45 @@ async function ossGenerateSTS() { reject() } }) + }, + multipartUpload: (data, progress) => { + return new Promise(async (resolve, reject) => { + try { + const { file, path } = data; + if (!file || !path) return reject('file and path be required'); + let config = await getSTSToken(Vue.prototype.OSSclientConfig.Expiration); + if (config) { + Vue.prototype.OSSclientConfig = { ...config.Result[res.Result.ObjectStoreUse] } + Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse; + Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint; + Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName + Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken + Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000 + OSSclient = new OSS(Vue.prototype.OSSclientConfig); + } + let _vm = router.default.app + if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { + var objectItem = data.path.split('/') + objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1] + data.path = objectItem.join('/') + } + let res = await customerHttp(OSSclient, data, progress); + if (res) { + resolve({ + name: data.path, + url: Vue.prototype.OSSclientConfig.viewEndpoint + res.name + }) + } else { + reject() + } + } catch (err) { + console.log(err) + reject(err) + } + }) + }, + close: () => { + OSSclose(); } } break @@ -86,6 +134,9 @@ async function ossGenerateSTS() { console.log(e) } }) + }, + close: () => { + return false } } break @@ -124,6 +175,47 @@ async function ossGenerateSTS() { console.log(e) } }) + }, + multipartUpload: (data, progress) => { + return new Promise(async (resolve, reject) => { + try { + const { file, path } = data; + if (!file || !path) return reject('file and path be required'); + let config = await getSTSToken(Vue.prototype.OSSclientConfig.Expiration); + if (config) { + Vue.prototype.OSSclientConfig = { ...config.Result[res.Result.ObjectStoreUse] } + Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse; + Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint; + Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName + Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken + Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000 + OSSclient = new S3Client(Vue.prototype.OSSclientConfig); + } + let _vm = router.default.app + if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') { + var objectItem = data.path.split('/') + objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1] + data.path = objectItem.join('/') + } + await exist(OSSclient, Vue.prototype.OSSclientConfig.bucket, data, progress, (res) => { + if (res) { + resolve({ + name: data.path, + url: Vue.prototype.OSSclientConfig.viewEndpoint + res.name + }) + } else { + reject() + } + }); + + } catch (err) { + console.log(err) + reject(err) + } + }) + }, + close: () => { + AWSclose(); } } } @@ -138,6 +230,47 @@ function decodeUtf8(bytes) { str2.pop(); return str2.join("/") + '/' + name; } +const queue = [] +let loading = false; +// 获取凭证 +function getSTSToken(credentials) { + return new Promise(async (resolve, reject) => { + let isExpired = isCredentialsExpired(credentials); + if (!isExpired) { + if (loading) { + queue.push({ resolve, reject }) + } + if (!loading) { + loading = true; + let res = await GetObjectStoreToken(); + loading = false; + resolve(res) + let p = queue.shift(); + while (p) { + p.resolve(res) + p = queue.shift(); + } + } + } else { + console.log("凭证未过期"); + resolve(false) + } + + }) +} +/** +* oss判断临时凭证是否到期。 +**/ +function isCredentialsExpired(credentials) { + if (!credentials) { + return true; + } + const expireDate = new Date(credentials.Expiration); + const now = new Date(); + // 如果有效期不足五分钟,视为过期。 + return expireDate.getTime() - now.getTime() <= 300000; + +} export const OSSclient = ossGenerateSTS diff --git a/src/views/trials/trials-panel/visit/crc-upload/components/uploadDicomFiles2.vue b/src/views/trials/trials-panel/visit/crc-upload/components/uploadDicomFiles2.vue index ab7beb7c..ccbcb19f 100644 --- a/src/views/trials/trials-panel/visit/crc-upload/components/uploadDicomFiles2.vue +++ b/src/views/trials/trials-panel/visit/crc-upload/components/uploadDicomFiles2.vue @@ -2,7 +2,7 @@
{{ - $t("trials:uploadedDicoms:title:dicomUploaded") + $t('trials:uploadedDicoms:title:dicomUploaded') }}
@@ -13,7 +13,7 @@ icon="el-icon-delete" @click="handleBatchDelete" > - {{ $t("trials:uploadedDicoms:action:delete") }} + {{ $t('trials:uploadedDicoms:action:delete') }} - {{ $t("trials:uploadedDicoms:action:preview") }} + {{ $t('trials:uploadedDicoms:action:preview') }}
- {{ $t("trials:uploadDicomList:table:status4") }} + {{ $t('trials:uploadDicomList:table:status4') }}
- {{ $t("trials:crc-upload:confirm:message") }} + {{ $t('trials:crc-upload:confirm:message') }}
{{ scope.row.StudyTime - ? moment(scope.row.StudyTime).format("YYYY-MM-DD") - : "" + ? moment(scope.row.StudyTime).format('YYYY-MM-DD') + : '' }} @@ -194,7 +194,7 @@
{{ - $t("trials:uploadedDicoms:title:dicomFilesOnly") + $t('trials:uploadedDicoms:title:dicomFilesOnly') }} @@ -211,7 +211,7 @@ :loading="btnLoading" size="small" >{{ - $t("trials:uploadedDicomsicom:button:selectFolder") + $t('trials:uploadedDicomsicom:button:selectFolder') }}
+ {{ + $store.state.trials.uploadTip + }} @@ -246,11 +249,11 @@ @@ -461,7 +475,7 @@
- {{ $t("trials:uploadDicomList:table:Existed") }}: + {{ $t('trials:uploadDicomList:table:Existed') }}:
 
- {{ $t("trials:uploadDicomList:table:Uploaded") }}: + {{ $t('trials:uploadDicomList:table:Uploaded') }}:
 

- {{ $t("trials:uploadDicomList:table:Failed") }}: + {{ $t('trials:uploadDicomList:table:Failed') }}:
- {{ $t("trials:uploadDicomList:button:upload") }} + {{ $t('trials:uploadDicomList:button:upload') }}
@@ -624,7 +638,7 @@
- {{ $t("trials:uploadDicomList:message:informationConsistent") }}: + {{ $t('trials:uploadDicomList:message:informationConsistent') }}:
{{ `(${i + 1}). ACC: ${item.accNumber}` }}
@@ -641,10 +655,10 @@
@@ -718,7 +732,7 @@ :key="bodyPart" :label="bodyPart" >{{ - $fd("Bodypart", bodyPart, "Code", BodyPart, "Name") + $fd('Bodypart', bodyPart, 'Code', BodyPart, 'Name') }} @@ -754,7 +768,7 @@ type="primary" @click="editStudyInfoVisible = false" > - {{ $t("common:button:cancel") }} + {{ $t('common:button:cancel') }} - {{ $t("common:button:save") }} + {{ $t('common:button:save') }}
@@ -777,11 +791,10 @@ import { updateModality, preArchiveDicomStudy, addOrUpdateArchiveStudy, - getCRCClinicalData, -} from "@/api/trials"; -import * as dicomParser from "dicom-parser"; -import * as cornerstone from "cornerstone-core"; -import * as cornerstoneWADOImageLoader from "cornerstone-wado-image-loader"; +} from '@/api/trials' +import * as dicomParser from 'dicom-parser' +import * as cornerstone from 'cornerstone-core' +import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' var config = { maxWebWorkers: 4, startWebWorkersOnDemand: true, @@ -790,27 +803,27 @@ var config = { initializeCodecsOnStartup: false, }, }, -}; -cornerstoneWADOImageLoader.webWorkerManager.initialize(config); -cornerstoneWADOImageLoader.external.dicomParser = dicomParser; -cornerstoneWADOImageLoader.external.cornerstone = cornerstone; -import DicomPreview from "@/views/dicom-show/dicom-preview"; -import uploadPetClinicalData from "./uploadPetClinicalData.vue"; -import dicomStore from "@/utils/dicom-store"; -import { getToken } from "@/utils/auth"; -import { dcmUpload } from "@/utils/dcmUpload/dcmUpload"; -import { convertBytes } from "@/utils/dicom-character-set"; -import moment from "moment"; -import store from "@/store"; -import uploadDicomPacs from "./uploadDiocmPacs.vue"; +} +cornerstoneWADOImageLoader.webWorkerManager.initialize(config) +cornerstoneWADOImageLoader.external.dicomParser = dicomParser +cornerstoneWADOImageLoader.external.cornerstone = cornerstone +import DicomPreview from '@/views/dicom-show/dicom-preview' +import uploadPetClinicalData from './uploadPetClinicalData.vue' +import dicomStore from '@/utils/dicom-store' +import { getToken } from '@/utils/auth' +import { dcmUpload } from '@/utils/dcmUpload/dcmUpload' +import { convertBytes } from '@/utils/dicom-character-set' +import moment from 'moment' +import store from '@/store' +import uploadDicomPacs from './uploadDiocmPacs.vue' export default { - name: "UploadDicomFiles", + name: 'UploadDicomFiles', components: { DicomPreview, uploadPetClinicalData, uploadDicomPacs }, props: { data: { type: Object, default() { - return {}; + return {} }, }, subjectVisitId: { @@ -828,24 +841,24 @@ export default { }, data() { return { - uploadActiveName: "file", + uploadActiveName: 'file', editStudyInfoVisible: false, studyForm: { - StudyCode: "", + StudyCode: '', IsDicomData: true, - Modalities: "", + Modalities: '', BodyPartForEdit: [], SeriesCount: null, - StudyTime: "", + StudyTime: '', }, uploadQueues: dicomStore.studyList, // 上传队列 selectArr: [], // 已勾选待上传文件 - scanState: "", // 当前上传队列上传状态 + scanState: '', // 当前上传队列上传状态 form: { - SiteName: "", - SubjectName: "", - VisitName: "", - SubjectId: "", + SiteName: '', + SubjectName: '', + VisitName: '', + SubjectId: '', VisitNum: null, }, btnLoading: false, @@ -856,7 +869,7 @@ export default { studyLoading: false, studyList: [], deleteArr: [], - trialId: "", + trialId: '', moment, uploadCount: 0, uploadedCount: 0, @@ -872,58 +885,60 @@ export default { petVisible: false, studyData: [], BodyPart: {}, - }; + } }, watch: { btnLoading() { - store.dispatch("trials/setUnLock", this.btnLoading); + store.dispatch('trials/setUnLock', this.btnLoading) }, }, async mounted() { - this.trialId = this.$route.query.trialId; - this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId); + this.trialId = this.$route.query.trialId + this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId) if (Object.keys(this.data).length) { - this.form = { ...this.data }; + this.form = { ...this.data } } - this.getStudyInfo(); - this.uploadQueues = []; + this.getStudyInfo() + this.uploadQueues = [] + this.OSSclient.close() }, beforeDestroy() { this.myInterval.forEach((v) => { - clearInterval(v); - }); - this.myInterval = []; - store.dispatch("trials/setUnLock", false); + clearInterval(v) + }) + this.myInterval = [] + store.dispatch('trials/setUnLock', false) + this.OSSclient.close() }, methods: { getParentList() { - this.getStudyInfo(); - this.$emit("getList"); + this.getStudyInfo() + this.$emit('getList') }, handleHistorical(row) { this.$router.push( `/trials/trials-panel/trial-summary/upload-monitor?trialId=${this.trialId}&trialCode=${this.$route.query.trialCode}&${this.$route.query.researchProgramNo}&studyCode=${row.StudyCode}` - ); + ) }, // 打开检查信息编辑框 handleEditStudy(row) { - this.editStudyInfoVisible = true; - this.studyForm = { ...row }; - var bodyPart = []; - if (this.studyForm.BodyPartForEdit.indexOf("|") !== -1) { - bodyPart = this.studyForm.BodyPartForEdit.split("|"); - } else if (this.studyForm.BodyPartForEdit !== "") { - bodyPart.push(this.studyForm.BodyPartForEdit); + this.editStudyInfoVisible = true + this.studyForm = { ...row } + var bodyPart = [] + if (this.studyForm.BodyPartForEdit.indexOf('|') !== -1) { + bodyPart = this.studyForm.BodyPartForEdit.split('|') + } else if (this.studyForm.BodyPartForEdit !== '') { + bodyPart.push(this.studyForm.BodyPartForEdit) } - this.$set(this.studyForm, "Modality", row.ModalityForEdit); - this.studyForm.BodyPartForEdit = bodyPart; + this.$set(this.studyForm, 'Modality', row.ModalityForEdit) + this.studyForm.BodyPartForEdit = bodyPart }, // 更新拍片部位/拍片类型信息 handleUpdateStudyInfo() { - this.$refs["studyForm"].validate((valid) => { - if (!valid) return; - this.btnLoading = true; - this.studyForm.BodyPart = this.studyForm.BodyPartForEdit.join("|"); + this.$refs['studyForm'].validate((valid) => { + if (!valid) return + this.btnLoading = true + this.studyForm.BodyPart = this.studyForm.BodyPartForEdit.join('|') // this.studyForm.Modality = this.studyForm.Modalities var params = { id: this.studyForm.StudyId, @@ -931,212 +946,217 @@ export default { type: 1, modality: this.studyForm.Modality, bodyPart: this.studyForm.BodyPart, - }; + } updateModality(this.trialId, params) .then((res) => { - this.btnLoading = false; + this.btnLoading = false if (res.IsSuccess) { - this.getStudyInfo(); - this.$message.success( - this.$t("common:message:savedSuccessfully") - ); - this.editStudyInfoVisible = false; + this.getStudyInfo() + this.$message.success(this.$t('common:message:savedSuccessfully')) + this.editStudyInfoVisible = false } }) .catch(() => { - this.btnLoading = false; - }); - }); + this.btnLoading = false + }) + }) }, format(v) { - return v; + return v }, // 获取已上传的dicom影像 getStudyInfo() { - this.studyLoading = true; + this.studyLoading = true getSubjectVisitUploadedStudyList(this.subjectVisitId) .then((res) => { // this.studyList = res.Result - this.relationInfo = res.OtherInfo; + this.relationInfo = res.OtherInfo this.trialBodyPartTypes = this.relationInfo.BodyPartTypes - ? this.relationInfo.BodyPartTypes.split("|") - : []; + ? this.relationInfo.BodyPartTypes.split('|') + : [] this.trialModalitys = this.relationInfo.Modalitys - ? this.relationInfo.Modalitys.split("|") - : []; - this.studyLoading = false; - this.studyList = res.Result; + ? this.relationInfo.Modalitys.split('|') + : [] + this.studyLoading = false + this.studyList = res.Result }) .catch(() => { - this.studyLoading = false; - }); + this.studyLoading = false + }) }, // 弹框提示pet-ct临床数据未上传 petDataTip(isPacs = false) { if (this.confirmFlag || isPacs) { - this.confirmFlag = false; + this.confirmFlag = false this.$confirm( - this.$t("trials:crc-upload:confirm:message"), - this.$t("trials:uploadDicomList:label:prompt"), + this.$t('trials:crc-upload:confirm:message'), + this.$t('trials:uploadDicomList:label:prompt'), { - confirmButtonText: this.$t("trials:reviewTrack:impactList:save"), + confirmButtonText: this.$t('trials:reviewTrack:impactList:save'), // cancelButtonText: this.$t("common:button:cancel"), - type: "warning", + type: 'warning', showCancelButton: false, } ) .then(() => { - this.confirmFlag = false; + this.confirmFlag = false }) .catch(() => { - this.confirmFlag = false; - }); + this.confirmFlag = false + }) } }, // 预览单个检查影像 handleViewStudy(row) { - var token = getToken(); + var token = getToken() const routeData = this.$router.resolve({ path: `/showdicom?studyId=${row.StudyId}&TokenKey=${token}&type=Study`, - }); - window.open(routeData.href, "_blank"); + }) + window.open(routeData.href, '_blank') }, // 打开上传pet临床数据弹框 handleUploadPetData(row) { - this.studyData = row; - this.studyData.SubjectId = this.subjectId; - this.petVisible = true; + this.studyData = row + this.studyData.SubjectId = this.subjectId + this.petVisible = true }, // 预览所有影像 handlePreviewAllFiles() { - var token = getToken(); - if (this.$route.path === "/trials/trials-panel/visit/crc-question") { + var token = getToken() + if (this.$route.path === '/trials/trials-panel/visit/crc-question') { var routeData = this.$router.resolve({ path: `/showvisitdicoms?trialId=${this.trialId}&visitInfo=${this.data.VisitName}(${this.data.VisitNum})&subjectVisitId=${this.data.SubjectVisitId}&isFromCRCUpload=1&TokenKey=${token}`, - }); + }) } else { var routeData = this.$router.resolve({ path: `/showvisitdicoms?trialId=${this.trialId}&visitInfo=${this.data.VisitName}(${this.data.VisitNum})&subjectVisitId=${this.data.Id}&isFromCRCUpload=1&TokenKey=${token}`, - }); + }) } - window.open(routeData.href, "_blank"); + window.open(routeData.href, '_blank') }, // 扫描待上传文件 beginScanFiles(e) { - var files = e.target.files; + var files = e.target.files if (files.length > 0) { - var checkFiles = [...files]; - var scope = this; - scope.scanState = ""; - scope.isScan = false; + var checkFiles = [...files] + let max = checkFiles.some((item) => item.size > 20 * 1024 * 1024 * 1024) + if (max) + return this.$message.warning( + this.$t('trials:uploadDicomList:message:maxFileSize') + ) + var scope = this + scope.scanState = '' + scope.isScan = false var p = new Promise(function (resolve) { - resolve(); - }); - var validFilesCount = 0; + resolve() + }) + var validFilesCount = 0 for (var i = 0; i < files.length; ++i) { - (function (index) { + ;(function (index) { p = p.then(function () { - if (files[index].name.toUpperCase().indexOf("DICOMDIR") === -1) { - validFilesCount = validFilesCount + 1; - return scope.parseDicomFile(files[index]); + if (files[index].name.toUpperCase().indexOf('DICOMDIR') === -1) { + validFilesCount = validFilesCount + 1 + return scope.parseDicomFile(files[index]) } - }); - })(i); + }) + })(i) } p.then(function (result) { scope.uploadQueues.forEach((v, i) => { - scope.$refs.dicomFilesTable.toggleRowSelection(v, true); - }); - scope.scanState = "finished"; - scope.isScan = true; - }); + scope.$refs.dicomFilesTable.toggleRowSelection(v, true) + }) + scope.scanState = 'finished' + scope.isScan = true + }) } }, // 按序列UUID本地归档 parseDicomFile(file) { - var scope = this; + var scope = this return new Promise(function (resolve, reject) { - if (scope.scanState === "cancelling") { - resolve(); - return; + if (scope.scanState === 'cancelling') { + resolve() + return } - var reader = new FileReader(); + var reader = new FileReader() reader.onload = function (e) { try { - var data = dicomParser.parseDicom(new Uint8Array(e.target.result)); - var instanceUid = data.string("x00080018"); - if (!instanceUid) return resolve(); - var modality = data.string("x00080060") || ""; - var studyUid = data.string("x0020000d"); - var pixelDataElement = data.elements.x7fe00010; - var studyIndex = 0; + var data = dicomParser.parseDicom(new Uint8Array(e.target.result)) + var instanceUid = data.string('x00080018') + if (!instanceUid) return resolve() + var modality = data.string('x00080060') || '' + var studyUid = data.string('x0020000d') + if (!studyUid) return resolve() + var pixelDataElement = data.elements.x7fe00010 + var studyIndex = 0 while ( studyIndex < scope.uploadQueues.length && scope.uploadQueues[studyIndex].dicomInfo.studyUid !== studyUid && - (pixelDataElement || modality === "SR") && - modality != "" + (pixelDataElement || modality === 'SR') && + modality != '' ) { - ++studyIndex; + ++studyIndex } if (studyIndex >= scope.uploadQueues.length) { - var date = data.string("x00080020"); - var time = data.string("x00080030"); - var studyTime = ""; + var date = data.string('x00080020') + var time = data.string('x00080030') + var studyTime = '' if (date) { date = `${date.substring(0, 4)}-${date.substring( 4, 6 - )}-${date.substring(6, 8)}`; + )}-${date.substring(6, 8)}` } if (time) { time = `${time.substring(0, 2)}:${time.substring( 2, 4 - )}:${time.substring(4, 6)}`; + )}:${time.substring(4, 6)}` } if (date) { - studyTime = time ? `${date} ${time}` : `${date} 00:00:00`; + studyTime = time ? `${date} ${time}` : `${date} 00:00:00` } - const patientNameElement = data.elements.x00100010; + const patientNameElement = data.elements.x00100010 const patientNameBytes = new Uint8Array( data.byteArray.buffer, patientNameElement ? patientNameElement.dataOffset : 0, patientNameElement ? patientNameElement.length : 0 - ); + ) const patientNameStr = convertBytes( - data.string("x00080005"), + data.string('x00080005'), patientNameBytes - ); + ) scope.uploadQueues.push({ studyIndex: studyIndex, seriesList: [], fileList: [], dicomInfo: { - studyId: data.string("x00200010"), + studyId: data.string('x00200010'), studyUid: studyUid, - patientId: data.string("x00100020"), + patientId: data.string('x00100020'), patientName: patientNameStr, - patientAge: data.string("x00101010") - ? data.string("x00101010") - : "", - patientSex: data.string("x00100040") - ? data.string("x00100040") - : "", - patientBirthDate: data.string("x00100030"), - hospitalName: data.string("x00080080"), - accNumber: data.string("x00080050"), - bodyPart: data.string("x00180015") || "", + patientAge: data.string('x00101010') + ? data.string('x00101010') + : '', + patientSex: data.string('x00100040') + ? data.string('x00100040') + : '', + patientBirthDate: data.string('x00100030'), + hospitalName: data.string('x00080080'), + accNumber: data.string('x00080050'), + bodyPart: data.string('x00180015') || '', modality: [], - institutionName: data.string("x00080080"), - description: data.string("x00081030"), + institutionName: data.string('x00080080'), + description: data.string('x00081030'), //0008,0032 - acquisitionTime: data.string("x00080032"), - acquisitionNumber: data.string("x00200012"), - triggerTime: data.string("x00181060"), + acquisitionTime: data.string('x00080032'), + acquisitionNumber: data.string('x00200012'), + triggerTime: data.string('x00181060'), studyTime: studyTime, VisitInfo: {}, SubjectInfo: {}, failedFileCount: 0, + uploadFileSize: 0, fileSize: 0, fileCount: 0, isInit: false, @@ -1144,170 +1164,169 @@ export default { uploadState: { selected: false, - stateCode: "", + stateCode: '', beginUploadTime: {}, progressValue: 0, }, - }); + }) } - var modality = scope.uploadQueues[studyIndex].dicomInfo.modality; - var currentModality = data.string("x00080060"); + var modality = scope.uploadQueues[studyIndex].dicomInfo.modality + var currentModality = data.string('x00080060') if (!(modality.indexOf(currentModality) > -1)) { - modality.push(currentModality); + modality.push(currentModality) } - var fileList = scope.uploadQueues[studyIndex].fileList; - var instanceUid = data.string("x00080018"); - var instanceIndex = 0; + var fileList = scope.uploadQueues[studyIndex].fileList + var instanceUid = data.string('x00080018') + var instanceIndex = 0 while ( instanceIndex < fileList.length && fileList[instanceIndex].instanceUid !== instanceUid && - (pixelDataElement || modality === "SR") + (pixelDataElement || modality === 'SR') ) { - ++instanceIndex; + ++instanceIndex } if (instanceIndex >= fileList.length) { fileList.push({ instanceUid: instanceUid, file: file, - }); + }) } - scope.uploadQueues[studyIndex].dicomInfo.fileCount = - fileList.length; + scope.uploadQueues[studyIndex].dicomInfo.fileCount = fileList.length scope.uploadQueues[studyIndex].dicomInfo.fileSize = fileList.reduce( (prev, next) => { - return prev + next.file.size; + return prev + next.file.size }, 0 - ); + ) - var seriesUid = data.string("x0020000e"); - var seriesList = scope.uploadQueues[studyIndex].seriesList; + var seriesUid = data.string('x0020000e') + var seriesList = scope.uploadQueues[studyIndex].seriesList var seriesItem = seriesList.find(function (item) { - return item.seriesUid === seriesUid; - }); - if (!seriesItem && (pixelDataElement || modality === "SR")) { - var date = data.string("x00080021"); - var time = data.string("x00080031"); - var seriesTime = ""; + return item.seriesUid === seriesUid + }) + if (!seriesItem && (pixelDataElement || modality === 'SR')) { + var date = data.string('x00080021') + var time = data.string('x00080031') + var seriesTime = '' if (date) { date = `${date.substring(0, 4)}-${date.substring( 4, 6 - )}-${date.substring(6, 8)}`; + )}-${date.substring(6, 8)}` } if (time) { time = `${time.substring(0, 2)}:${time.substring( 2, 4 - )}:${time.substring(4, 6)}`; + )}:${time.substring(4, 6)}` } if (date) { - seriesTime = time ? `${date} ${time}` : `${date} 00:00:00`; + seriesTime = time ? `${date} ${time}` : `${date} 00:00:00` } - const seriesDescriptionElement = data.elements.x0008103e; + const seriesDescriptionElement = data.elements.x0008103e const seriesDescriptionBytes = new Uint8Array( data.byteArray.buffer, seriesDescriptionElement ? seriesDescriptionElement.dataOffset : 0, seriesDescriptionElement ? seriesDescriptionElement.length : 0 - ); + ) const seriesDescriptionStr = convertBytes( - data.string("x00080005"), + data.string('x00080005'), seriesDescriptionBytes - ); + ) seriesItem = { seriesUid: seriesUid, - seriesNumber: data.intString("x00200011") || 1, - modality: data.string("x00080060") || "", + seriesNumber: data.intString('x00200011') || 1, + modality: data.string('x00080060') || '', description: seriesDescriptionStr, seriesTime: seriesTime, - sliceThickness: data.string("x00180050") || "", - imagePositionPatient: data.string("x00200032") || "", - imageOrientationPatient: data.string("x00200037") || "", - sequenceName: data.string("x00180024") || "", - protocolName: data.string("x00181030") || "", - imagerPixelSpacing: data.string("x00181164") || "", + sliceThickness: data.string('x00180050') || '', + imagePositionPatient: data.string('x00200032') || '', + imageOrientationPatient: data.string('x00200037') || '', + sequenceName: data.string('x00180024') || '', + protocolName: data.string('x00181030') || '', + imagerPixelSpacing: data.string('x00181164') || '', instanceList: [], - }; - seriesList.push(seriesItem); + } + seriesList.push(seriesItem) } - var instanceList = seriesItem.instanceList; + var instanceList = seriesItem.instanceList var instanceItem = instanceList.find(function (item) { - return item.instanceUid === instanceUid; - }); + return item.instanceUid === instanceUid + }) if (!instanceItem) { - var date = data.string("x00080023"); - var time = data.string("x00080033"); - var instanceTime = ""; + var date = data.string('x00080023') + var time = data.string('x00080033') + var instanceTime = '' if (date) { date = `${date.substring(0, 4)}-${date.substring( 4, 6 - )}-${date.substring(6, 8)}`; + )}-${date.substring(6, 8)}` } if (time) { time = `${time.substring(0, 2)}:${time.substring( 2, 4 - )}:${time.substring(4, 6)}`; + )}:${time.substring(4, 6)}` } if (date) { - instanceTime = time ? `${date} ${time}` : `${date} 00:00:00`; + instanceTime = time ? `${date} ${time}` : `${date} 00:00:00` } instanceItem = { instanceUid: instanceUid, - instanceNumber: data.intString("x00200013") || 1, - frameCount: data.intString("x00280008") || 1, + instanceNumber: data.intString('x00200013') || 1, + frameCount: data.intString('x00280008') || 1, instanceTime: instanceTime, - imageRows: data.uint16("x00280010") || 0, - imageColumns: data.uint16("x00280011") || 0, - sliceLocation: data.intString("x00201041") || 0, - sliceThickness: data.string("x00180050") || "", - numberOfFrames: data.intString("x00280008") || 0, - pixelSpacing: data.string("x00280030") || "", - imagerPixelSpacing: data.string("x00181164") || "", - frameOfReferenceUID: data.string("x00200052") || "", - windowCenter: data.string("x00281050") || "", - windowWidth: data.string("x00281051") || "", - modality: data.string("x00080060") || "", + imageRows: data.uint16('x00280010') || 0, + imageColumns: data.uint16('x00280011') || 0, + sliceLocation: data.intString('x00201041') || 0, + sliceThickness: data.string('x00180050') || '', + numberOfFrames: data.intString('x00280008') || 0, + pixelSpacing: data.string('x00280030') || '', + imagerPixelSpacing: data.string('x00181164') || '', + frameOfReferenceUID: data.string('x00200052') || '', + windowCenter: data.string('x00281050') || '', + windowWidth: data.string('x00281051') || '', + modality: data.string('x00080060') || '', file: file, - }; - instanceList.push(instanceItem); + } + instanceList.push(instanceItem) } - resolve(); + resolve() } catch (error) { - console.log(error); - resolve(); + console.log(error) + resolve() } - }; + } reader.onerror = function (e) { - resolve(); - }; - reader.readAsArrayBuffer(file); - }); + resolve() + } + reader.readAsArrayBuffer(file) + }) }, // 上传之前校验基本信息及检查是否已上传 beginUploadQueues() { - this.scanState = "uploading"; - this.studyErrorList = []; + this.scanState = 'uploading' + this.studyErrorList = [] // console.log(this.uploadQueues, this.selectArr) - this.warningArr = []; + this.warningArr = [] for (let i = 0; i < this.selectArr.length; ++i) { - const index = this.selectArr[i].studyIndex; - this.uploadQueues[index].uploadState.stateCode = "uploading"; - this.verifyBasicInfos(index); + const index = this.selectArr[i].studyIndex + this.uploadQueues[index].uploadState.stateCode = 'uploading' + this.verifyBasicInfos(index) } if (this.warningArr.length) { - this.warning_cfg.visible = true; - this.btnLoading = false; + this.warning_cfg.visible = true + this.btnLoading = false } else { - this.verifyStudy(); + this.verifyStudy() } }, // 校验影像中检查时间、性别是否与受试者匹配 verifyBasicInfos(index) { - var warnings = []; + var warnings = [] if ( this.uploadQueues[index].dicomInfo.patientSex && this.form.SubjectSex @@ -1317,8 +1336,8 @@ export default { this.form.SubjectSex.substr(0, 1) ) { warnings.push( - this.$t("trials:uploadDicomList:message:genderConsistent") - ); + this.$t('trials:uploadDicomList:message:genderConsistent') + ) } } if (warnings.length > 0) { @@ -1326,46 +1345,46 @@ export default { index: this.uploadQueues[index].studyIndex + 1, accNumber: this.uploadQueues[index].dicomInfo.accNumber, warnings: warnings, - }); + }) } }, // 校验该检查是否上传过 verifyStudy() { - this.btnLoading = true; - var studyList = []; + this.btnLoading = true + var studyList = [] this.selectArr.forEach((item) => { if (!item.uploadState.selected) { studyList.push({ studyInstanceUid: item.dicomInfo.studyUid, studyDate: item.dicomInfo.studyTime, - }); + }) } - }); + }) var param = { trialId: this.trialId, subjectId: this.subjectId, subjectVisitId: this.subjectVisitId, visitNum: this.form.VisitNum, studyInstanceUidList: studyList, - }; + } batchVerifyStudyAllowUpload(param) .then(async (res) => { - var messageArr = []; + var messageArr = [] res.Result.forEach((item) => { const i = this.uploadQueues.findIndex( (value) => value.dicomInfo.studyUid === item.StudyInstanceUid - ); - let instanceUidList = []; + ) + let instanceUidList = [] item.UploadedSeriesList.forEach((v) => { v.SOPInstanceUIDList.forEach((v1) => { - instanceUidList.push(v1); - }); - }); + instanceUidList.push(v1) + }) + }) // isReUploadinstanceUidList1.includes(instanceUidList2) try { this.uploadQueues[i].seriesList.forEach((v) => { let o = item.UploadedSeriesList.find((v1) => { - return v.seriesUid === v1.SeriesId; + return v.seriesUid === v1.SeriesId // v.instanceList.forEach(v2 => { // let o2 = v1.SOPInstanceUIDList.find(v3 => { // return v3 === v2.instanceUid @@ -1374,171 +1393,171 @@ export default { // v2.isReUpload = true // } // }) - }); + }) if (!!o) { - v.isReUpload = true; + v.isReUpload = true } - }); + }) this.uploadQueues[i].seriesList.forEach((v) => { v.instanceList.forEach((v2) => { let o2 = instanceUidList.find((v3) => { - return v3 === v2.instanceUid; - }); + return v3 === v2.instanceUid + }) if (!!o2) { - v2.isReUpload = true; + v2.isReUpload = true } - }); - }); + }) + }) } catch (e) { - console.log(e); + console.log(e) } // 不能上传或不能重传时,收集校验结果提示,并取消勾选,设置上传状态 if (item.ErrorMesseage) { this.uploadQueues[i].uploadState.AllowReUpload = - item.AllowReUpload; + item.AllowReUpload this.$refs.dicomFilesTable.toggleRowSelection( this.uploadQueues[i] - ); - this.uploadQueues[i].uploadState.selected = true; - const msg = `${item.ErrorMesseage}`; - messageArr.push(msg); + ) + this.uploadQueues[i].uploadState.selected = true + const msg = `${item.ErrorMesseage}` + messageArr.push(msg) } // 可以重传时,记录需要被覆盖的检查ID if (item.AllowReUpload) { this.uploadQueues[i].AbandonStudyId = item.StudyInfo ? item.StudyInfo.Id - : ""; + : '' } - this.uploadQueues[i].uploadState.AllowReUpload = item.AllowReUpload; - }); + this.uploadQueues[i].uploadState.AllowReUpload = item.AllowReUpload + }) if (messageArr.length > 0) { var li = messageArr.map((msg) => { - return `
  • ${msg}
  • `; - }); + return `
  • ${msg}
  • ` + }) const content = `
      - ${li.join("")} + ${li.join('')}
    -
    `; +
    ` this.$alert( content, - this.$t("trials:uploadDicomList:label:prompt"), + this.$t('trials:uploadDicomList:label:prompt'), { confirmButtonText: this.$t( - "trials:uploadDicomList:label:confirm" + 'trials:uploadDicomList:label:confirm' ), dangerouslyUseHTMLString: true, callback: (action) => {}, } - ); - this.btnLoading = false; + ) + this.btnLoading = false } - var results = []; - this.uploadCount = this.selectArr.length; - this.uploadedCount = 0; + var results = [] + this.uploadCount = this.selectArr.length + this.uploadedCount = 0 for (let i = 0; i < this.selectArr.length; i++) { - const index = this.selectArr[i].studyIndex; + const index = this.selectArr[i].studyIndex if (!this.uploadQueues[index].uploadState.selected) { - await this.archiveStudy(index, res.OtherInfo); + await this.archiveStudy(index, res.OtherInfo) } } - this.$set(this, "uploadQueues", [ + this.$set(this, 'uploadQueues', [ ...this.uploadQueues.filter((v) => { return ( !v.uploadState.record || (v.uploadState.record && !!v.uploadState.record.Failed.length) - ); + ) }), - ]); + ]) this.$nextTick(() => { - this.selectArr = []; + this.selectArr = [] this.uploadQueues.forEach((v, i) => { if (v.uploadState.record) { - v.uploadState.selected = false; - this.$refs.dicomFilesTable.toggleRowSelection(v, true); + v.uploadState.selected = false + this.$refs.dicomFilesTable.toggleRowSelection(v, true) } - v.studyIndex = i; - }); - this.$refs.pathClear.value = ""; - this.btnLoading = false; + v.studyIndex = i + }) + this.$refs.pathClear.value = '' + this.btnLoading = false // console.log(11111); if (this.studyErrorList.length > 0) { let msg = this.$t( - "trials:uploadDicomFiles2:message:studyErrorList" - ); - msg = msg.replaceAll("xxx", this.studyErrorList.join("、")); - this.$confirm(msg, this.$t("trials:hotkeys:message:tip"), { + 'trials:uploadDicomFiles2:message:studyErrorList' + ) + msg = msg.replaceAll('xxx', this.studyErrorList.join('、')) + this.$confirm(msg, this.$t('trials:hotkeys:message:tip'), { confirmButtonText: this.$t( - "trials:uploadDicomFiles2:button:reupload" + 'trials:uploadDicomFiles2:button:reupload' ), }).then(() => { - this.beginUploadQueues(); - }); + this.beginUploadQueues() + }) } if (this.confirmFlag) { - this.petDataTip(); + this.petDataTip() } - }); + }) }) .catch((_) => { - this.btnLoading = false; - }); + this.btnLoading = false + }) }, objectToQuery() { - let obj = arguments[0]; - let prefix = arguments[1]; - if (typeof obj !== "object") return ""; - const attrs = Object.keys(obj); + let obj = arguments[0] + let prefix = arguments[1] + if (typeof obj !== 'object') return '' + const attrs = Object.keys(obj) return attrs.reduce((query, attr, index) => { // 判断是否是第一层第一个循环 - if (index === 0 && !prefix) query += "?"; - if (typeof obj[attr] === "object") { - const subPrefix = prefix ? `${prefix}[${attr}]` : attr; - query += this.objectToQuery(obj[attr], subPrefix); + if (index === 0 && !prefix) query += '?' + if (typeof obj[attr] === 'object') { + const subPrefix = prefix ? `${prefix}[${attr}]` : attr + query += this.objectToQuery(obj[attr], subPrefix) } else { if (prefix) { - query += `${prefix}[${attr}]=${obj[attr]}`; + query += `${prefix}[${attr}]=${obj[attr]}` } else { - query += `${attr}=${obj[attr]}`; + query += `${attr}=${obj[attr]}` } } // 判断是否是第一层最后一个循环 - if (index !== attrs.length - 1) query += "&"; - return query; - }, ""); + if (index !== attrs.length - 1) query += '&' + return query + }, '') }, canvasToBlob(canvas) { return new Promise((resolve) => { canvas.toBlob((blob) => { - resolve(blob); - }); - }); + resolve(blob) + }) + }) }, dicomToPng(imageId, width, height) { return new Promise((resolve) => { cornerstone.loadImage(imageId).then(async (image) => { - let canvas = document.createElement("canvas"); - canvas.width = width; - canvas.height = height; + let canvas = document.createElement('canvas') + canvas.width = width + canvas.height = height if (image) { - cornerstone.renderToCanvas(canvas, image); + cornerstone.renderToCanvas(canvas, image) // 将 Canvas 图像对象转换为 PNG 格式 - let blob = await this.canvasToBlob(canvas); - resolve(blob); + let blob = await this.canvasToBlob(canvas) + resolve(blob) } else { - resolve(); + resolve() } - }); + }) }).catch((reason) => { - reason(); - }); + reason() + }) }, // 上传影像并归档 archiveStudy(index, config) { - var scope = this; + var scope = this return new Promise(function (resolve, reject) { try { preArchiveDicomStudy({ @@ -1553,31 +1572,31 @@ export default { scope.uploadQueues[index].uploadState.AllowReUpload, }) .then(async (res) => { - scope.uploadQueues[index].dicomInfo.failedFileCount = 0; - scope.$set(scope.uploadQueues[index].dicomInfo, "isInit", true); - let dicomInfo = scope.uploadQueues[index].dicomInfo; - let seriesNum = scope.uploadQueues[index].seriesList.length; - let fileNum = scope.uploadQueues[index].fileList.length; - let seriesList = scope.uploadQueues[index].seriesList; - let fileList = scope.uploadQueues[index].fileList; - dicomInfo.seriesNum = seriesNum; - dicomInfo.fileNum = fileNum; - dicomInfo.trialSiteId = scope.data.TrialSiteId; - dicomInfo.subjectId = scope.data.SubjectId; - dicomInfo.subjectVisitId = scope.subjectVisitId; + scope.uploadQueues[index].dicomInfo.failedFileCount = 0 + scope.$set(scope.uploadQueues[index].dicomInfo, 'isInit', true) + let dicomInfo = scope.uploadQueues[index].dicomInfo + let seriesNum = scope.uploadQueues[index].seriesList.length + let fileNum = scope.uploadQueues[index].fileList.length + let seriesList = scope.uploadQueues[index].seriesList + let fileList = scope.uploadQueues[index].fileList + dicomInfo.seriesNum = seriesNum + dicomInfo.fileNum = fileNum + dicomInfo.trialSiteId = scope.data.TrialSiteId + dicomInfo.subjectId = scope.data.SubjectId + dicomInfo.subjectVisitId = scope.subjectVisitId let t = setInterval(() => { dicomUploadInProgress({ trialId: scope.trialId, studyInstanceUid: dicomInfo.studyUid, - }).then((res) => {}); - }, 5000); - scope.myInterval.push(t); + }).then((res) => {}) + }, 5000) + scope.myInterval.push(t) let Record = { Failed: [], Existed: [], Uploaded: [], FileCount: 0, - }; + } let params = { trialId: scope.trialId, trialSiteId: scope.data.TrialSiteId, @@ -1595,34 +1614,35 @@ export default { instanceCount: dicomInfo.fileNum, institutionName: dicomInfo.institutionName, patientId: config.DicomStoreInfo.SubjectCode, - patientName: "", - patientAge: "", + patientName: '', + patientAge: '', patientSex: config.DicomStoreInfo.SubjectSex, accessionNumber: dicomInfo.accNumber, - patientBirthDate: "", + patientBirthDate: '', acquisitionTime: dicomInfo.acquisitionTime, acquisitionNumber: dicomInfo.acquisitionNumber, triggerTime: dicomInfo.triggerTime, - bodyPartExamined: "", + bodyPartExamined: '', seriesList: [], }, - }; - let arr = []; + } + let arr = [] for (let i = 0; i < seriesList.length; i++) { - let v = seriesList[i]; - let instanceList = []; - let ImageResizePath; + let v = seriesList[i] + let instanceList = [] + let ImageResizePath for (let ii = 0; ii < v.instanceList.length; ii++) { arr.push( (function () { return new Promise(async (resolve1) => { try { - let o = v.instanceList[ii]; - let name = `${v.instanceList[ii].file.webkitRelativePath}_${v.instanceList[ii].instanceUid}`; + let o = v.instanceList[ii] + let name = `${v.instanceList[ii].file.webkitRelativePath}_${v.instanceList[ii].instanceUid}` if (o.isReUpload) { - dicomInfo.failedFileCount++; - Record.Existed.push(name); - Record.FileCount++; + dicomInfo.failedFileCount++ + dicomInfo.uploadFileSize += o.file.size + Record.Existed.push(name) + Record.FileCount++ } else if (o.myPath) { instanceList.push({ studyInstanceUid: dicomInfo.studyUid, @@ -1641,10 +1661,10 @@ export default { windowCenter: o.windowCenter, windowWidth: o.windowWidth, path: o.myPath, - }); - Record.Uploaded.push(name); - dicomInfo.failedFileCount++; - Record.FileCount++; + }) + Record.Uploaded.push(name) + dicomInfo.failedFileCount++ + Record.FileCount++ } else { let path = `/${params.trialId}/Image/${ params.trialSiteId @@ -1655,35 +1675,51 @@ export default { v.seriesUid + o.instanceUid + params.trialId - )}`; - let res = await dcmUpload(path, o.file, config); + )}` + let res = await dcmUpload( + { + path: path, + file: o.file, + speed: true, + }, + config, + (percentage, checkpoint, lastPer) => { + dicomInfo.uploadFileSize += + checkpoint.size * (percentage - lastPer) + if ( + dicomInfo.uploadFileSize > dicomInfo.fileSize + ) { + dicomInfo.uploadFileSize = dicomInfo.fileSize + } + } + ) if (!res || !res.url) { - params.failedFileCount++; + params.failedFileCount++ } else { - if (ii === 0 && o.modality !== "SR") { + if (ii === 0 && o.modality !== 'SR') { try { let fileId = cornerstoneWADOImageLoader.wadouri.fileManager.add( o.file - ); + ) let blob = await scope.dicomToPng( fileId, o.imageColumns, o.imageRows - ); - let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.png`; - let OSSclient = scope.OSSclient; + ) + let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.png` + let OSSclient = scope.OSSclient let seriesRes = await OSSclient.put( thumbnailPath, blob - ); + ) if (seriesRes && seriesRes.url) { ImageResizePath = scope.$getObjectName( seriesRes.url - ); + ) } } catch (e) { - console.log(e); + console.log(e) } } } @@ -1705,27 +1741,27 @@ export default { windowCenter: o.windowCenter, windowWidth: o.windowWidth, path: scope.$getObjectName(res.url), - }); - o.myPath = scope.$getObjectName(res.url); - Record.Uploaded.push(name); - dicomInfo.failedFileCount++; - Record.FileCount++; + }) + o.myPath = scope.$getObjectName(res.url) + Record.Uploaded.push(name) + dicomInfo.failedFileCount++ + Record.FileCount++ } else { - Record.Failed.push(name); - Record.FileCount++; + Record.Failed.push(name) + Record.FileCount++ } } - resolve1(); + resolve1() } catch (e) { - console.log(e); - resolve1(); + console.log(e) + resolve1() } - }); + }) })() - ); - if (arr.length >= 66 || ii === v.instanceList.length - 1) { - await Promise.all(arr); - arr = []; + ) + if (arr.length >= 10 || ii === v.instanceList.length - 1) { + await Promise.all(arr) + arr = [] } } params.study.seriesList.push({ @@ -1748,92 +1784,93 @@ export default { bodyPartExamined: dicomInfo.bodyPart, instanceList: instanceList, ImageResizePath: ImageResizePath, - }); + }) } - let text = JSON.stringify(Record); - let logJsonBlob = scope.generateTxtFile(text); - let logJsonObjectName = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${params.studyMonitorId}.txt`; - let logRes; + let text = JSON.stringify(Record) + let logJsonBlob = scope.generateTxtFile(text) + let logJsonObjectName = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${params.studyMonitorId}.txt` + let logRes try { logRes = await scope.OSSclient.put( logJsonObjectName, logJsonBlob - ); + ) } catch (e) { - scope.uploadQueues[index].uploadState.record = Record; - scope.studyErrorList.push(dicomInfo.accNumber); - clearInterval(t); - resolve(); + scope.uploadQueues[index].uploadState.record = Record + scope.studyErrorList.push(dicomInfo.accNumber) + clearInterval(t) + resolve() } for (let i = 0; i < seriesList.length; i++) { - let v = seriesList[i]; + let v = seriesList[i] let o = params.study.seriesList.find((o) => { - return o.seriesInstanceUid === v.seriesUid; - }); + return o.seriesInstanceUid === v.seriesUid + }) if (o && !o.ImageResizePath) { let fileId = cornerstoneWADOImageLoader.wadouri.fileManager.add( v.instanceList[0].file - ); + ) let blob = await scope.dicomToPng( fileId, v.instanceList[0].imageColumns, v.instanceList[0].imageRows - ); - let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.png`; - let OSSclient = scope.OSSclient; + ) + let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.png` + let OSSclient = scope.OSSclient try { - let seriesRes = await OSSclient.put(thumbnailPath, blob); + let seriesRes = await OSSclient.put(thumbnailPath, blob) if (seriesRes && seriesRes.url) { - o.ImageResizePath = scope.$getObjectName(seriesRes.url); + o.ImageResizePath = scope.$getObjectName(seriesRes.url) } } catch (e) { - console.log(e); + console.log(e) } } } if (logRes && logRes.url) { - params.study.instanceCount = dicomInfo.failedFileCount; - params.RecordPath = scope.$getObjectName(logRes.url); + params.study.instanceCount = dicomInfo.failedFileCount + params.RecordPath = scope.$getObjectName(logRes.url) + console.log(params) addOrUpdateArchiveStudy(params) .then((res) => { if (dicomInfo.failedFileCount === dicomInfo.fileCount) { scope.$message.success( - scope.$t("trials:uploadDicomList:label:uploaded") - ); + scope.$t('trials:uploadDicomList:label:uploaded') + ) } else { - scope.studyErrorList.push(dicomInfo.accNumber); + scope.studyErrorList.push(dicomInfo.accNumber) } - scope.uploadQueues[index].uploadState.record = Record; + scope.uploadQueues[index].uploadState.record = Record let flag = - res.Result === "PET-CT" || - res.Result === "CT、PT" || - res.Result === "PT、CT"; + res.Result === 'PET-CT' || + res.Result === 'CT、PT' || + res.Result === 'PT、CT' // let flag = params.study.seriesList.some(item=>item.modality==='PT'); if (flag && scope.relationInfo.IsHaveStudyClinicalData) { - scope.confirmFlag = true; + scope.confirmFlag = true } - scope.getStudyInfo(); + scope.getStudyInfo() if ( scope.$route.path !== - "/trials/trials-panel/visit/crc-question" + '/trials/trials-panel/visit/crc-question' ) { - scope.$emit("getList"); + scope.$emit('getList') } - clearInterval(t); - resolve(); + clearInterval(t) + resolve() }) .catch((res) => { - scope.uploadQueues[index].uploadState.record = Record; - scope.studyErrorList.push(dicomInfo.accNumber); - clearInterval(t); - resolve(); - }); + scope.uploadQueues[index].uploadState.record = Record + scope.studyErrorList.push(dicomInfo.accNumber) + clearInterval(t) + resolve() + }) } else { - scope.uploadQueues[index].uploadState.record = Record; - scope.studyErrorList.push(dicomInfo.accNumber); - clearInterval(t); - resolve(); + scope.uploadQueues[index].uploadState.record = Record + scope.studyErrorList.push(dicomInfo.accNumber) + clearInterval(t) + resolve() } }) .catch(() => { @@ -1842,200 +1879,200 @@ export default { Existed: [], Uploaded: [], FileCount: 0, - }; - let fileList = scope.uploadQueues[index].fileList; + } + let fileList = scope.uploadQueues[index].fileList fileList.forEach((v) => { - Record.Failed.push(v.webkitRelativePath); - }); - scope.uploadQueues[index].uploadState.record = Record; - scope.studyErrorList.push(dicomInfo.accNumber); - resolve(); - }); + Record.Failed.push(v.webkitRelativePath) + }) + scope.uploadQueues[index].uploadState.record = Record + scope.studyErrorList.push(dicomInfo.accNumber) + resolve() + }) } catch (e) { - console.log(e); - resolve(); + console.log(e) + resolve() } - }); + }) }, generateTxtFile(text) { - let blob = new Blob(["\ufeff", text], { type: "text/plain" }); - return blob; + let blob = new Blob(['\ufeff', text], { type: 'text/plain' }) + return blob }, // warning弹框取消按钮回调 handleCancelWarnVisible() { - this.warning_cfg.visible = false; + this.warning_cfg.visible = false for (var i = 0; i < this.selectArr.length; ++i) { - const index = this.selectArr[i].studyIndex; - this.uploadQueues[index].uploadState.stateCode = ""; + const index = this.selectArr[i].studyIndex + this.uploadQueues[index].uploadState.stateCode = '' } }, // 忽略warning继续上传 handleContinueUpload() { - this.warning_cfg.visible = false; - this.verifyStudy(); + this.warning_cfg.visible = false + this.verifyStudy() }, // 预览影像 handlePreview(uid) { - this.previewVisible = true; - this.uid = uid; + this.previewVisible = true + this.uid = uid }, // 删除影像列表中的某个影像 handleDelete(index, row) { - this.$confirm(this.$t("trials:uploadedDicoms:message:deleteMes"), { - type: "warning", + this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), { + type: 'warning', distinguishCancelAndClose: true, }).then(() => { - this.$refs.uploadForm.reset(); - this.uploadQueues.splice(index, 1); + this.$refs.uploadForm.reset() + this.uploadQueues.splice(index, 1) this.uploadQueues.forEach((v, i) => { if (v.uploadState.record) { - v.uploadState.selected = false; - this.$refs.dicomFilesTable.toggleRowSelection(v, true); + v.uploadState.selected = false + this.$refs.dicomFilesTable.toggleRowSelection(v, true) } - v.studyIndex = i; - }); - this.handleSelectionChange(this.uploadQueues); - }); + v.studyIndex = i + }) + this.handleSelectionChange(this.uploadQueues) + }) }, // 当选择项发生变化时收集待上传文件数据 handleSelectionChange(selection) { selection.sort((n1, n2) => { - return n1.studyIndex - n2.studyIndex; - }); - this.selectArr = selection; + return n1.studyIndex - n2.studyIndex + }) + this.selectArr = selection }, // 根据是否上传状态决定CheckBox 是否可以勾选 handleSelectable(row) { if (row.uploadState.selected || this.btnLoading) { - return false; + return false } else { - return true; + return true } }, // 收集已上传文件列表勾选项 handleUploadedSelectionChange(selection) { - this.deleteArr = []; + this.deleteArr = [] selection.forEach((item) => { - this.deleteArr.push(item.StudyId); - }); + this.deleteArr.push(item.StudyId) + }) }, // 批量删除已上传的影像 handleBatchDelete() { - this.$confirm(this.$t("trials:uploadedDicoms:message:deleteMes"), { - type: "warning", + this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), { + type: 'warning', distinguishCancelAndClose: true, }) .then(() => { - this.studyLoading = true; + this.studyLoading = true deleteStudyList(this.trialId, this.subjectVisitId, this.deleteArr) .then((res) => { if (res.IsSuccess) { - this.getStudyInfo(); + this.getStudyInfo() if ( - this.$route.path !== "/trials/trials-panel/visit/crc-question" + this.$route.path !== '/trials/trials-panel/visit/crc-question' ) { - this.$emit("getList"); + this.$emit('getList') } this.$message.success( - this.$t("trials:uploadedDicoms:message:deleteSuccessfully") - ); + this.$t('trials:uploadedDicoms:message:deleteSuccessfully') + ) } }) .catch(() => { - this.studyLoading = true; - }); + this.studyLoading = true + }) }) - .catch(() => {}); + .catch(() => {}) }, // 删除已上传的某个检查 handleDeleteStudy(row) { - this.$confirm(this.$t("trials:uploadedDicoms:message:deleteMes"), { - type: "warning", + this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), { + type: 'warning', distinguishCancelAndClose: true, }) .then(() => { - this.studyLoading = true; + this.studyLoading = true deleteStudyList(this.trialId, this.subjectVisitId, [row.StudyId]) .then((res) => { if (res.IsSuccess) { - this.getStudyInfo(); - if (this.uploadActiveName === "pacs") { - this.$refs.dicomPacs.getList(); + this.getStudyInfo() + if (this.uploadActiveName === 'pacs') { + this.$refs.dicomPacs.getList() } if ( - this.$route.path !== "/trials/trials-panel/visit/crc-question" + this.$route.path !== '/trials/trials-panel/visit/crc-question' ) { - this.$emit("getList"); + this.$emit('getList') } this.$message.success( - this.$t("trials:uploadedDicoms:message:deleteSuccessfully") - ); + this.$t('trials:uploadedDicoms:message:deleteSuccessfully') + ) } }) .catch(() => { - this.studyLoading = true; - }); + this.studyLoading = true + }) }) - .catch(() => {}); + .catch(() => {}) }, // cancel按钮回调 cancel() { - this.scanState = "cancelling"; + this.scanState = 'cancelling' // 关闭上传模态框 - this.$emit("close"); + this.$emit('close') }, compare(start, end) { - start = new Date(start); - start = start.getTime(); - end = new Date(end); - end = end.getTime(); - var time = 0; + start = new Date(start) + start = start.getTime() + end = new Date(end) + end = end.getTime() + var time = 0 if (start > end) { - time = start - end; + time = start - end } else { - time = end - start; + time = end - start } - return Math.floor(time / 86400000); + return Math.floor(time / 86400000) }, exportFailedFiles(errorFiles) { - var elementA = document.createElement("a"); - var str = ""; + var elementA = document.createElement('a') + var str = '' errorFiles.forEach((el) => { - str += el + "\n"; - }); - elementA.setAttribute("href", "data:text/html;charset=utf-8," + str); - elementA.setAttribute("download", +new Date() + ".txt"); - elementA.style.display = "none"; - document.body.appendChild(elementA); - elementA.click(); - document.body.removeChild(elementA); + str += el + '\n' + }) + elementA.setAttribute('href', 'data:text/html;charset=utf-8,' + str) + elementA.setAttribute('download', +new Date() + '.txt') + elementA.style.display = 'none' + document.body.appendChild(elementA) + elementA.click() + document.body.removeChild(elementA) }, // 设置已删除序列行样式 tableRowClassName({ row, rowIndex }) { if (row.IsDeleted) { - return "delete-row"; + return 'delete-row' } else { - return ""; + return '' } }, getBodyPart(bodyPart) { - if (!bodyPart) return ""; - var separator = ","; - if (bodyPart.indexOf("|") > -1) { - separator = "|"; - } else if (bodyPart.indexOf(",") > -1) { - separator = ","; - } else if (bodyPart.indexOf(",") > -1) { - separator = ","; + if (!bodyPart) return '' + var separator = ',' + if (bodyPart.indexOf('|') > -1) { + separator = '|' + } else if (bodyPart.indexOf(',') > -1) { + separator = ',' + } else if (bodyPart.indexOf(',') > -1) { + separator = ',' } - var arr = bodyPart.split(separator); + var arr = bodyPart.split(separator) var newArr = arr.map((i) => { - return this.$fd("Bodypart", i.trim(), "Code", this.BodyPart, "Name"); - }); - return newArr.join(" | "); + return this.$fd('Bodypart', i.trim(), 'Code', this.BodyPart, 'Name') + }) + return newArr.join(' | ') }, }, -}; +} diff --git a/vue.config.js b/vue.config.js index 21dac50b..ea3e8bf9 100644 --- a/vue.config.js +++ b/vue.config.js @@ -16,7 +16,7 @@ const name = process.env.NODE_ENV === 'usa' ? 'LILI' : defaultSettings.title || // eslint-disable-next-line no-undef module.exports = { // lintOnSave: false, - transpileDependencies: ['@cornerstonejs', 'minio'], + transpileDependencies: ['@cornerstonejs', 'minio', '@aws-sdk', '@smithy'], publicPath: process.env.NODE_ENV === 'development' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? process.env.VUE_APP_BASE_PATH : `${process.env.VUE_FILE_PATH}${process.env.VUE_APP_OSS_PATH}${distDate}/`, // publicPath: '/', outputDir: 'dist',