Compare commits
17 Commits
v1.6.0
...
2303c04857
| Author | SHA1 | Date | |
|---|---|---|---|
| 2303c04857 | |||
| beeadfbdeb | |||
| b866ffdd49 | |||
| 8ad50b5618 | |||
| e517556808 | |||
| 1a8653b47e | |||
| bfe86e6868 | |||
| f0eda2bc66 | |||
| 8f274aad89 | |||
| 709063a26e | |||
| 9e786c53b8 | |||
| 37520fccb6 | |||
| f3b36b9127 | |||
| 870354b4b2 | |||
| f838df51a5 | |||
| 0a6a98c33c | |||
| 28c357a702 |
@@ -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",
|
||||
|
||||
@@ -39,4 +39,12 @@ export function deleteTaskStudy(params) {
|
||||
method: 'delete',
|
||||
params
|
||||
})
|
||||
}
|
||||
// 获取iqc下载文件信息
|
||||
export function getCRCUploadedStudyInfo(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/getCRCUploadedStudyInfo',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
@@ -81,16 +81,25 @@
|
||||
<!-- <div v-show="stack.firstImageLoading" class="load-indicator">
|
||||
Loading Series #{{ stack.seriesNumber }}...
|
||||
</div>-->
|
||||
<el-dialog
|
||||
v-if="dcmTag.visible"
|
||||
:visible.sync="dcmTag.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="dcmTag.title"
|
||||
width="1000px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
append-to-body
|
||||
>
|
||||
<DicomTags :image-data="imageData" @close="dcmTag.visible = false" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Vue from 'vue'
|
||||
import Contextmenu from 'vue-contextmenujs'
|
||||
Vue.use(Contextmenu)
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import * as cornerstoneMath from 'cornerstone-math'
|
||||
import * as cornerstoneTools from 'cornerstone-tools'
|
||||
|
||||
const scroll = cornerstoneTools.import('util/scrollToIndex')
|
||||
import Hammer from 'hammerjs'
|
||||
import getOrientationString from '@/views/trials/trials-panel/reading/dicoms/tools/OrientationMarkers/getOrientationString'
|
||||
@@ -108,8 +117,10 @@ cornerstoneTools.toolColors.setActiveColor('rgb(0, 255, 0)')
|
||||
// cornerstoneTools.init({ showSVGCursors: true })
|
||||
cornerstoneTools.init()
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
import DicomTags from './DicomTags'
|
||||
export default {
|
||||
name: 'DicomCanvas',
|
||||
components: { DicomTags },
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
@@ -164,7 +175,9 @@ export default {
|
||||
mousePosition: { x: '', y: '', mo: '' },
|
||||
markers: { top: '', right: '', bottom: '', left: '' },
|
||||
orientationMarkers: [],
|
||||
originalMarkers: []
|
||||
originalMarkers: [],
|
||||
dcmTag: { visible: false, title: 'DICOM Tags' },
|
||||
imageData: null
|
||||
}
|
||||
},
|
||||
|
||||
@@ -215,7 +228,7 @@ export default {
|
||||
cornerstoneTools.stopClip(this.canvas)
|
||||
this.toolState.clipPlaying = false
|
||||
this.loading = true
|
||||
|
||||
|
||||
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
|
||||
.then(image => {
|
||||
this.loading = false
|
||||
@@ -364,8 +377,8 @@ export default {
|
||||
if (this.dicomInfo.thick) {
|
||||
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
|
||||
}
|
||||
let newImageIdIndex = this.stack.imageIds.findIndex(i=>i===e.detail.image.imageId)
|
||||
if(newImageIdIndex === -1) return
|
||||
const newImageIdIndex = this.stack.imageIds.findIndex(i => i === e.detail.image.imageId)
|
||||
if (newImageIdIndex === -1) return
|
||||
this.stack.currentImageIdIndex = newImageIdIndex
|
||||
this.stack.imageIdIndex = newImageIdIndex
|
||||
this.series.imageIdIndex = newImageIdIndex
|
||||
@@ -441,7 +454,7 @@ export default {
|
||||
if (!markers) {
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
|
||||
this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
|
||||
this.setMarkers()
|
||||
@@ -636,7 +649,7 @@ export default {
|
||||
enabledElement.renderingTools.renderCanvasData = renderCanvasData
|
||||
},
|
||||
scrollPage(offset) {
|
||||
if(this.loading) return
|
||||
if (this.loading) return
|
||||
var index = this.stack.currentImageIdIndex + offset
|
||||
if (index < 0) index = 0
|
||||
else if (index >= this.stack.imageIds.length) {
|
||||
@@ -648,7 +661,7 @@ export default {
|
||||
},
|
||||
|
||||
toggleClipPlay() {
|
||||
if(this.loading) return
|
||||
if (this.loading) return
|
||||
if (this.toolState.clipPlaying) {
|
||||
cornerstoneTools.stopClip(this.canvas)
|
||||
this.toolState.clipPlaying = false
|
||||
@@ -707,7 +720,7 @@ export default {
|
||||
this.orientationMarkers = [...this.originalMarkers]
|
||||
this.setMarkers()
|
||||
}
|
||||
|
||||
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.hflip = false
|
||||
viewport.vflip = false
|
||||
@@ -747,6 +760,13 @@ export default {
|
||||
var uid = cornerstone.getImage(this.canvas).data.string('x00080018')
|
||||
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
|
||||
},
|
||||
showTags() {
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
// var dataSet = dicomParser.parseDicom(image.data.byteArray)
|
||||
// console.log('showTags', dataSet)
|
||||
this.dcmTag.visible = true
|
||||
this.imageData = image.data
|
||||
},
|
||||
fitToWindow() {
|
||||
if (this.stack.seriesNumber) {
|
||||
cornerstone.fitToWindow(this.canvas)
|
||||
|
||||
@@ -0,0 +1,261 @@
|
||||
<template>
|
||||
<div class="dcm-tag">
|
||||
<el-input
|
||||
v-model="search"
|
||||
size="mini"
|
||||
placeholder="输入关键字搜索"
|
||||
style="width:200px"
|
||||
/>
|
||||
|
||||
<el-table
|
||||
:data="filterList(list)"
|
||||
row-key="id"
|
||||
default-expand-all
|
||||
:tree-props="{children: 'child', hasChildren: 'hasChildren'}"
|
||||
:default-sort="{prop: 'tagCode', order: 'ascending'}"
|
||||
height="500"
|
||||
>
|
||||
<el-table-column
|
||||
prop="tagCode"
|
||||
label="Tag"
|
||||
min-width="120"
|
||||
sortable
|
||||
/>
|
||||
<el-table-column
|
||||
prop="tagName"
|
||||
label="Description"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
sortable
|
||||
/>
|
||||
<el-table-column
|
||||
prop="vr"
|
||||
label="VR"
|
||||
min-width="50"
|
||||
show-overflow-tooltip
|
||||
sortable
|
||||
/>
|
||||
<el-table-column
|
||||
prop="tagLength"
|
||||
label="Length"
|
||||
min-width="80"
|
||||
show-overflow-tooltip
|
||||
sortable
|
||||
/>
|
||||
<el-table-column
|
||||
prop="value"
|
||||
label="Value"
|
||||
min-width="200"
|
||||
show-overflow-tooltip
|
||||
sortable
|
||||
/>
|
||||
</el-table>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import TAG_DICT from './dataDictionary'
|
||||
import dicomParser from 'dicom-parser'
|
||||
export default {
|
||||
name: 'DicomTags',
|
||||
props: {
|
||||
imageData: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
list: [],
|
||||
idx: 0,
|
||||
search: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var dataSet = dicomParser.parseDicom(this.imageData.byteArray)
|
||||
var output = []
|
||||
this.dumpDataSet(dataSet, output)
|
||||
this.list = output
|
||||
},
|
||||
methods: {
|
||||
filterList(list) {
|
||||
if (list.length === 0) return []
|
||||
if (!this.search) {
|
||||
return list
|
||||
} else {
|
||||
return list.filter(data => data.tagCode.toLowerCase().includes(this.search.toLowerCase()) || data.tagName.toLowerCase().includes(this.search.toLowerCase()) || (data.value && data.value.toLowerCase().includes(this.search.toLowerCase())))
|
||||
}
|
||||
},
|
||||
dumpDataSet(dataSet, output) {
|
||||
try {
|
||||
for (const propertyName in dataSet.elements) {
|
||||
const elementObject = {}
|
||||
const element = dataSet.elements[propertyName]
|
||||
const tag = this.getTag(element.tag)
|
||||
elementObject.id = `${this.idx++}${new Date().getTime()}`
|
||||
elementObject.tagCode = element.tag
|
||||
elementObject.tagName = tag.name
|
||||
elementObject.tagLength = element.length
|
||||
elementObject.value = ''
|
||||
|
||||
if (element.vr) {
|
||||
elementObject.vr = element.vr
|
||||
}
|
||||
elementObject.child = []
|
||||
|
||||
if (element.items) {
|
||||
element.items.forEach(item => {
|
||||
const childOutput = []
|
||||
this.dumpDataSet(item.dataSet, childOutput)
|
||||
elementObject.child.push(...childOutput)
|
||||
})
|
||||
} else if (element.fragments) {
|
||||
// 多帧处理
|
||||
} else {
|
||||
var vr
|
||||
if (element.vr !== undefined) {
|
||||
vr = element.vr
|
||||
}
|
||||
if (element.length < 128) {
|
||||
// const str = dataSet.string(propertyName)
|
||||
// if (elementObject.tagCode === 'x00280010') {
|
||||
// console.log(str)
|
||||
// }
|
||||
// const stringIsAscii = this.isASCII(str)
|
||||
// if (stringIsAscii && str !== undefined) {
|
||||
// elementObject.value = str
|
||||
// }
|
||||
|
||||
if (element.vr === undefined && tag === undefined) {
|
||||
if (element.length === 2) {
|
||||
elementObject.value = dataSet.uint16(propertyName)
|
||||
} else if (element.length === 4) {
|
||||
elementObject.value = dataSet.uint32(propertyName)
|
||||
}
|
||||
const str = dataSet.string(propertyName)
|
||||
const stringIsAscii = this.isASCII(str)
|
||||
|
||||
if (stringIsAscii) {
|
||||
if (str !== undefined) {
|
||||
elementObject.value = str
|
||||
}
|
||||
} else {
|
||||
if (element.length !== 2 && element.length !== 4) {
|
||||
// elementObject.value = 'binary data'
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.isStringVr(vr)) {
|
||||
const str = dataSet.string(propertyName)
|
||||
const stringIsAscii = this.isASCII(str)
|
||||
|
||||
if (stringIsAscii) {
|
||||
if (str !== undefined) {
|
||||
elementObject.value = str
|
||||
}
|
||||
} else {
|
||||
if (element.length !== 2 && element.length !== 4) {
|
||||
// elementObject.value = 'binary data'
|
||||
}
|
||||
}
|
||||
} else if (vr === 'US') {
|
||||
let text = dataSet.uint16(propertyName)
|
||||
for (let i = 1; i < dataSet.elements[propertyName].length / 2; i++) {
|
||||
text += '\\' + dataSet.uint16(propertyName, i)
|
||||
}
|
||||
elementObject.value = text
|
||||
} else if (vr === 'SS') {
|
||||
let text = dataSet.int16(propertyName)
|
||||
for (let i = 1; i < dataSet.elements[propertyName].length / 2; i++) {
|
||||
text += '\\' + dataSet.int16(propertyName, i)
|
||||
}
|
||||
elementObject.value = text
|
||||
} else if (vr === 'UL') {
|
||||
let text = dataSet.uint32(propertyName)
|
||||
for (let i = 1; i < dataSet.elements[propertyName].length / 4; i++) {
|
||||
text += '\\' + dataSet.uint32(propertyName, i)
|
||||
}
|
||||
elementObject.value = text
|
||||
} else if (vr === 'SL') {
|
||||
let text = dataSet.int32(propertyName)
|
||||
for (let i = 1; i < dataSet.elements[propertyName].length / 4; i++) {
|
||||
text += '\\' + dataSet.int32(propertyName, i)
|
||||
}
|
||||
elementObject.value = text
|
||||
} else if (vr === 'FD') {
|
||||
let text = dataSet.double(propertyName)
|
||||
for (let i = 1; i < dataSet.elements[propertyName].length / 8; i++) {
|
||||
text += '\\' + dataSet.double(propertyName, i)
|
||||
}
|
||||
elementObject.value = text
|
||||
} else if (vr === 'FL') {
|
||||
let text = dataSet.float(propertyName)
|
||||
for (let i = 1; i < dataSet.elements[propertyName].length / 4; i++) {
|
||||
text += '\\' + dataSet.float(propertyName, i)
|
||||
}
|
||||
elementObject.value = text
|
||||
} else if (vr === 'OB' || vr === 'OW' || vr === 'UN' || vr === 'OF' || vr === 'UT') {
|
||||
if (element.length === 2) {
|
||||
elementObject.value = dataSet.uint16(propertyName)
|
||||
} else if (element.length === 4) {
|
||||
elementObject.value = dataSet.uint32(propertyName)
|
||||
} else {
|
||||
|
||||
}
|
||||
} else if (vr === 'AT') {
|
||||
// var group = dataSet.uint16(propertyName, 0);
|
||||
// var groupHexStr = ("0000" + group.toString(16)).substr(-4);
|
||||
// var element = dataSet.uint16(propertyName, 1);
|
||||
// var elementHexStr = ("0000" + element.toString(16)).substr(-4);
|
||||
// text += "x" + groupHexStr + elementHexStr;
|
||||
} else if (vr === 'SQ') {
|
||||
} else {
|
||||
// no display code for VR yet, sorry!
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
output.push(elementObject)
|
||||
}
|
||||
} catch (err) {
|
||||
const ex = {
|
||||
exception: err,
|
||||
output: output
|
||||
}
|
||||
throw ex
|
||||
}
|
||||
},
|
||||
getTag(tag) {
|
||||
var group = tag.substring(1, 5)
|
||||
var element = tag.substring(5, 9)
|
||||
var tagIndex = ('(' + group + ',' + element + ')').toUpperCase()
|
||||
var attr = TAG_DICT[tagIndex]
|
||||
return attr
|
||||
},
|
||||
isASCII(str) {
|
||||
return /^[\x00-\x7F]*$/.test(str)
|
||||
},
|
||||
isStringVr(vr) {
|
||||
if (vr === 'AT' || vr === 'FL' || vr === 'FD' || vr === 'OB' || vr === 'OF' || vr === 'OW' || vr === 'SI' || vr === 'SQ' || vr === 'SS' || vr === 'UL' || vr === 'US') {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.dcm-tag{
|
||||
// user-select: none;
|
||||
::-webkit-scrollbar {
|
||||
width: 8px;
|
||||
height: 15px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -182,7 +182,7 @@
|
||||
<svg-icon icon-class="fitToImage" style="font-size:20px;" />
|
||||
</button>
|
||||
<!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> -->
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<!-- 测量标注 -->
|
||||
@@ -233,6 +233,10 @@
|
||||
<button :title="$t('trials:dicom-show:image')" class="btn-link" @click="currentDicomCanvas.saveImage()">
|
||||
<svg-icon icon-class="image" style="font-size:20px;" />
|
||||
</button>
|
||||
<!-- 标签 -->
|
||||
<button :title="$t('trials:dicom-show:tags')" class="btn-link" @click="currentDicomCanvas.showTags()">
|
||||
<svg-icon icon-class="dictionary" style="font-size:20px;" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="measureTool-wrapper">
|
||||
@@ -405,7 +409,7 @@ export default {
|
||||
loadImageStack(dicomSeries) {
|
||||
this.currentDicomCanvas.toolState.clipPlaying = false
|
||||
this.$nextTick(() => {
|
||||
let series = Object.assign({}, dicomSeries)
|
||||
const series = Object.assign({}, dicomSeries)
|
||||
this.currentDicomCanvas.loadImageStack(series)
|
||||
})
|
||||
},
|
||||
@@ -416,7 +420,7 @@ export default {
|
||||
Array.from(elements).forEach((element, index) => {
|
||||
const canvasIndex = element.getAttribute('data-index')
|
||||
if (index < seriesList.length && element.style.display !== 'none') {
|
||||
let series = Object.assign({}, seriesList[index])
|
||||
const series = Object.assign({}, seriesList[index])
|
||||
this.$refs[`dicomCanvas${canvasIndex}`].loadImageStack(series)
|
||||
}
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+13
-16
@@ -28,25 +28,22 @@ Vue.use(permission)
|
||||
|
||||
import Viewer from 'v-viewer'
|
||||
import './assets/css/viewer.css'
|
||||
|
||||
Vue.use(Viewer)
|
||||
Viewer.setDefaults({
|
||||
Options: {
|
||||
'inline': true,
|
||||
'button': true,
|
||||
'navbar': true,
|
||||
'title': true,
|
||||
'toolbar': true,
|
||||
'tooltip': true,
|
||||
'movable': true,
|
||||
'zoomable': true,
|
||||
'rotatable': true,
|
||||
'scalable': true,
|
||||
'transition': true,
|
||||
'keyboard': true,
|
||||
'url': 'data-source'
|
||||
// navbar: true, //底部缩略图
|
||||
toolbar: {
|
||||
zoomIn: true,
|
||||
zoomOut: true,
|
||||
reset: true,
|
||||
prev: true,
|
||||
next: true,
|
||||
rotateLeft: true,
|
||||
rotateRight: true,
|
||||
flipHorizontal: true,
|
||||
flipVertical: true,
|
||||
}
|
||||
})
|
||||
Vue.use(Viewer)
|
||||
|
||||
|
||||
import hasPermi from './directive/permission'
|
||||
Vue.use(hasPermi)
|
||||
|
||||
@@ -9,7 +9,7 @@ const getDefaultState = () => {
|
||||
studyListQuery: null,
|
||||
unlock: false,
|
||||
config: {},
|
||||
uploadTip: null,
|
||||
uploadTip: '0.00kb/s',
|
||||
timer: null,
|
||||
whiteList: [],
|
||||
checkTaskId: null
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,459 @@
|
||||
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);
|
||||
timer = null;
|
||||
store.state.trials.uploadTip = '0kb/s'
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
import moment from "moment";
|
||||
import store from "@/store";
|
||||
let savaData = {},
|
||||
checkData = {}, // 当前上传的节点文件和上一次提交进度
|
||||
timer = null, // 网速定时器
|
||||
bytesReceivedPerSecond = {}; // 时间节点上传文件总量
|
||||
export function OSSclose() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
store.state.trials.uploadTip = '0kb/s'
|
||||
}
|
||||
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)
|
||||
}
|
||||
+1
File diff suppressed because one or more lines are too long
+140
-6
@@ -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()
|
||||
@@ -23,12 +22,23 @@ async function ossGenerateSTS() {
|
||||
switch (res.Result.ObjectStoreUse) {
|
||||
case 'AliyunOSS':
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken
|
||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
|
||||
Vue.prototype.OSSclient = {
|
||||
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 +59,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 +135,9 @@ async function ossGenerateSTS() {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
},
|
||||
close: () => {
|
||||
return false
|
||||
}
|
||||
}
|
||||
break
|
||||
@@ -124,6 +176,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 +231,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
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
import streamSaver from "streamsaver";
|
||||
import "streamsaver/examples/zip-stream.js";
|
||||
|
||||
// 下载文件并压缩
|
||||
function zipFiles(zipName, files) {
|
||||
console.log("同步下载打包开始时间:" + new Date());
|
||||
// 创建压缩文件输出流
|
||||
const zipFileOutputStream = streamSaver.createWriteStream(zipName);
|
||||
// 创建下载文件流
|
||||
const fileIterator = files.values();
|
||||
const readableZipStream = new ZIP({
|
||||
async pull(ctrl) {
|
||||
const fileInfo = fileIterator.next();
|
||||
if (fileInfo.done) {//迭代终止
|
||||
ctrl.close();
|
||||
} else {
|
||||
const { name, url } = fileInfo.value;
|
||||
return fetch(url).then(res => {
|
||||
ctrl.enqueue({
|
||||
name,
|
||||
stream: () => res.body
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
if (window.WritableStream && readableZipStream.pipeTo) {
|
||||
// 开始下载
|
||||
readableZipStream
|
||||
.pipeTo(zipFileOutputStream)
|
||||
.then(() => console.log("同步下载打包结束时间:" + new Date()));
|
||||
}
|
||||
}
|
||||
// 下载文件并修改名称
|
||||
async function updateFile(file, name) {
|
||||
try {
|
||||
const fileOutputStream = streamSaver.createWriteStream(name);
|
||||
let res = await fetch(file);
|
||||
res.body.pipeTo(fileOutputStream);
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
export function downLoadFile(file, name, type = 'file') {
|
||||
if (type === 'zip') return zipFiles(name, file);
|
||||
return updateFile(file, name)
|
||||
|
||||
}
|
||||
@@ -49,7 +49,7 @@
|
||||
<el-table-column prop="Identification" label="标识" :show-overflow-tooltip="true" min-width="200px" />
|
||||
<el-table-column prop="OptTypeValueCN" label="操作类型" show-overflow-tooltip width="100px" />
|
||||
<el-table-column prop="ObjectTypeValueCN" label="对象类型" show-overflow-tooltip min-width="100px" />
|
||||
<el-table-column prop="ChildrenTypeValueCN" label="数据类型" show-overflow-tooltip min-width="100px" show-overflow-tooltip />
|
||||
<el-table-column prop="ChildrenTypeValueCN" label="数据类型" show-overflow-tooltip min-width="100px"/>
|
||||
<el-table-column
|
||||
prop="Sort"
|
||||
label="显示顺序"
|
||||
@@ -110,7 +110,7 @@
|
||||
|
||||
<!-- 添加或修改菜单对话框 -->
|
||||
<el-dialog :title="title" top="100px" :close-on-click-modal="false" id="check_config" :visible.sync="open" :width="form.DataType === 'Table' ? '1280px' : '680px'" append-to-body>
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="100px">
|
||||
<el-form ref="form" :model="form" :rules="rules" label-width="120px">
|
||||
<el-row>
|
||||
<el-col v-show="title !== '复制'" :span="24">
|
||||
<el-divider content-position="left">基本信息</el-divider>
|
||||
@@ -372,6 +372,16 @@
|
||||
<el-input :disabled="!scope.row.IsFixedColumn" v-model="scope.row.FixedColumnName" placeholder="固定列名"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="FixedColumnEnName"
|
||||
min-width="120"
|
||||
label="固定列名EN"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-input :disabled="!scope.row.IsFixedColumn" v-model="scope.row.FixedColumnEnName" placeholder="固定列名EN"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ColumnName"
|
||||
min-width="120"
|
||||
@@ -382,6 +392,16 @@
|
||||
<el-input :disabled="scope.row.IsFixedColumn" v-model="scope.row.ColumnName" placeholder="列字段名"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ColumnEnName"
|
||||
min-width="120"
|
||||
label="列字段名En"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-input :disabled="scope.row.IsFixedColumn" v-model="scope.row.ColumnEnName" placeholder="列字段名En"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="ColumnValue"
|
||||
min-width="120"
|
||||
@@ -415,6 +435,16 @@
|
||||
<el-input :disabled="!scope.row.IsMerge" v-model="scope.row.MergeColumnName" placeholder="合并组"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="MergeColumnEnName"
|
||||
min-width="120"
|
||||
label="合并组EN"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-input :disabled="!scope.row.IsMerge" v-model="scope.row.MergeColumnEnName" placeholder="合并组EN"/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop="IsPicture"
|
||||
min-width="120"
|
||||
@@ -489,6 +519,14 @@
|
||||
<el-input v-model="form.ChildDataLabel" placeholder="请输入子数据Lable" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制' && form.DataType === 'Array'" :span="12">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
子数据LableEN
|
||||
</span>
|
||||
<el-input v-model="form.ChildDataEnLabel" placeholder="请输入子数据LableEN" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制' && form.DataType === 'Array'" :span="12">
|
||||
<el-form-item>
|
||||
<span slot="label">
|
||||
@@ -559,6 +597,11 @@
|
||||
<el-input v-model="form.ForeignKeyText" placeholder="请输入数据库字段to" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制' && form.EnumType === 'Foreign'" :span="12">
|
||||
<el-form-item label="字段toEN">
|
||||
<el-input v-model="form.ForeignKeyEnText" placeholder="请输入数据库字段toEN" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
</el-col>
|
||||
<el-col v-show="title !== '复制'" :span="24">
|
||||
@@ -821,10 +864,13 @@ export default {
|
||||
ListName: null,
|
||||
IsFixedColumn: false,
|
||||
FixedColumnName: null,
|
||||
FixedColumnEnName: null,
|
||||
ColumnName: null,
|
||||
ColumnEnName: null,
|
||||
ColumnValue: null,
|
||||
IsMerge: false,
|
||||
MergeColumnName: null,
|
||||
MergeColumnEnName: null,
|
||||
IsPicture: false,
|
||||
IsDynamicTranslate: false,
|
||||
IsNeedTransalate: false,
|
||||
@@ -1111,6 +1157,7 @@ export default {
|
||||
IsSpecialType: false,
|
||||
DataType: '',
|
||||
ChildDataLabel: null,
|
||||
ChildDataEnLabel: null,
|
||||
ChildDataValue: null,
|
||||
DateType: null,
|
||||
DictionaryCode: null,
|
||||
@@ -1118,6 +1165,7 @@ export default {
|
||||
ForeignKeyTableName: null,
|
||||
ForeignKeyValue: null,
|
||||
ForeignKeyText: null,
|
||||
ForeignKeyEnText: null,
|
||||
TableConfigList: [],
|
||||
UrlConfig: {
|
||||
RoutePath: null,
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
</el-form-item>
|
||||
<!-- 阅片标准 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:trials-list:table:IR_ReadingCriterionList')"
|
||||
v-if="hasPermi(['role:ir'])"
|
||||
:label="$t('trials:trials-list:table:IR_ReadingCriterionList')"
|
||||
>
|
||||
<el-select
|
||||
v-model="searchData.CriterionType"
|
||||
@@ -59,8 +59,8 @@
|
||||
</el-form-item>
|
||||
<!-- 联系人 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:trials-list:table:IR_PMEmailList')"
|
||||
v-if="hasPermi(['role:ir'])"
|
||||
:label="$t('trials:trials-list:table:IR_PMEmailList')"
|
||||
>
|
||||
<el-input
|
||||
v-model="searchData.PM_EMail"
|
||||
@@ -293,9 +293,10 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button type="primary" @click="handleSelectSearch"
|
||||
>Search</el-button
|
||||
>
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleSelectSearch"
|
||||
>Search</el-button>
|
||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||
<el-button type="primary" @click="isShow = false">Back</el-button>
|
||||
</el-form-item>
|
||||
@@ -357,23 +358,19 @@
|
||||
<el-tag
|
||||
v-if="scope.row.TrialStatusStr === 'Initializing'"
|
||||
type="info"
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
|
||||
>
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag>
|
||||
<el-tag
|
||||
v-if="scope.row.TrialStatusStr === 'Ongoing'"
|
||||
type="primary"
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
|
||||
>
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag>
|
||||
<el-tag
|
||||
v-if="scope.row.TrialStatusStr === 'Completed'"
|
||||
type="warning"
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
|
||||
>
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag>
|
||||
<el-tag
|
||||
v-if="scope.row.TrialStatusStr === 'Stopped'"
|
||||
type="danger"
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag
|
||||
>
|
||||
>{{ $fd("TrialStatusEnum", scope.row.TrialStatusStr) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -582,7 +579,7 @@
|
||||
:disabled="
|
||||
(scope.row.TrialStatusStr === 'Initializing' &&
|
||||
!hasPermi(['role:pm'])) ||
|
||||
scope.row.IsDeleted
|
||||
scope.row.IsDeleted || ((scope.row.TrialStatusStr === 'Completed' || scope.row.TrialStatusStr === 'Stopped') && !(hasPermi(['role:qa']) || hasPermi(['role:ea']) || hasPermi(['role:pm'])))
|
||||
"
|
||||
:title="$t('trials:trials-list:action:panel')"
|
||||
@click.stop="handleDetail(scope.row)"
|
||||
@@ -612,7 +609,7 @@
|
||||
icon="el-icon-delete"
|
||||
:disabled="
|
||||
scope.row.IsDeleted ||
|
||||
scope.row.TrialStatusStr !== 'Initializing'
|
||||
scope.row.TrialStatusStr !== 'Initializing'
|
||||
"
|
||||
:title="$t('trials:trials-list:action:abolition')"
|
||||
@click.stop="handleAbandon(scope.row)"
|
||||
@@ -693,54 +690,54 @@
|
||||
import {
|
||||
abandonTrial,
|
||||
ifTrialCanOngoing,
|
||||
getTrialToBeDoneList,
|
||||
} from "@/api/trials";
|
||||
import { getTrialList_Export } from "@/api/export";
|
||||
import store from "@/store";
|
||||
import { mapGetters } from "vuex";
|
||||
import BaseContainer from "@/components/BaseContainer";
|
||||
import Pagination from "@/components/Pagination";
|
||||
import TrialForm from "./components/TrialForm";
|
||||
import TrialStatusForm from "./components/TrialStatusForm";
|
||||
import DoneList from "./components/DoneList";
|
||||
getTrialToBeDoneList
|
||||
} from '@/api/trials'
|
||||
import { getTrialList_Export } from '@/api/export'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import TrialForm from './components/TrialForm'
|
||||
import TrialStatusForm from './components/TrialStatusForm'
|
||||
import DoneList from './components/DoneList'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
Code: "",
|
||||
Code: '',
|
||||
CriterionIds: [],
|
||||
SponsorId: "",
|
||||
SponsorId: '',
|
||||
ReviewTypeIds: [],
|
||||
CROId: "",
|
||||
Expedited: "",
|
||||
Indication: "",
|
||||
Phase: "",
|
||||
CROId: '',
|
||||
Expedited: '',
|
||||
Indication: '',
|
||||
Phase: '',
|
||||
ModalityIds: [],
|
||||
BeginDate: "",
|
||||
EndDate: "",
|
||||
AttendedReviewerType: "",
|
||||
ResearchProgramNo: "",
|
||||
ExperimentName: "",
|
||||
BeginDate: '',
|
||||
EndDate: '',
|
||||
AttendedReviewerType: '',
|
||||
ResearchProgramNo: '',
|
||||
ExperimentName: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: false,
|
||||
SortField: "",
|
||||
SortField: '',
|
||||
CriterionType: null,
|
||||
PM_EMail: null,
|
||||
};
|
||||
};
|
||||
PM_EMail: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: "Trials",
|
||||
name: 'Trials',
|
||||
components: {
|
||||
Pagination,
|
||||
BaseContainer,
|
||||
TrialForm,
|
||||
TrialStatusForm,
|
||||
DoneList,
|
||||
DoneList
|
||||
},
|
||||
dicts: ["ReadingStandard", "ReviewType", "ReadingType"],
|
||||
dicts: ['ReadingStandard', 'ReviewType', 'ReadingType'],
|
||||
data() {
|
||||
return {
|
||||
exportLoading: false,
|
||||
userTypeEnumInt: zzSessionStorage.getItem("userTypeEnumInt") * 1,
|
||||
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
|
||||
doneDialogVisible: false,
|
||||
doneTitle: null,
|
||||
selectArr: [],
|
||||
@@ -750,26 +747,26 @@ export default {
|
||||
total: 0,
|
||||
isShow: false,
|
||||
dialogVisible: false,
|
||||
title: "",
|
||||
currentId: "",
|
||||
title: '',
|
||||
currentId: '',
|
||||
statusVisible: false,
|
||||
currentRow: {},
|
||||
currentUser: zzSessionStorage.getItem("userName"),
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
phaseOptions: [
|
||||
{ value: "I" },
|
||||
{ value: "II" },
|
||||
{ value: "III" },
|
||||
{ value: "IV" },
|
||||
{ value: 'I' },
|
||||
{ value: 'II' },
|
||||
{ value: 'III' },
|
||||
{ value: 'IV' }
|
||||
],
|
||||
expeditedOption: this.$d.TrialExpeditedState,
|
||||
beginPickerOption: {
|
||||
disabledDate: (time) => {
|
||||
if (this.searchData.EndDate) {
|
||||
return time.getTime() > new Date(this.searchData.EndDate).getTime();
|
||||
return time.getTime() > new Date(this.searchData.EndDate).getTime()
|
||||
} else {
|
||||
return time.getTime() > Date.now();
|
||||
return time.getTime() > Date.now()
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
endpickerOption: {
|
||||
disabledDate: (time) => {
|
||||
@@ -777,306 +774,189 @@ export default {
|
||||
return (
|
||||
time.getTime() > Date.now() ||
|
||||
time.getTime() <= new Date(this.searchData.BeginDate).getTime()
|
||||
);
|
||||
)
|
||||
} else {
|
||||
return time.getTime() > Date.now();
|
||||
return time.getTime() > Date.now()
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["sponsorList", "croList"]),
|
||||
...mapGetters(['sponsorList', 'croList'])
|
||||
},
|
||||
created() {
|
||||
this.initPage();
|
||||
this.initPage()
|
||||
},
|
||||
methods: {
|
||||
initPage() {
|
||||
this.getList();
|
||||
store.dispatch("global/getSponsorList");
|
||||
store.dispatch("global/getCROList");
|
||||
this.getList()
|
||||
store.dispatch('global/getSponsorList')
|
||||
store.dispatch('global/getCROList')
|
||||
},
|
||||
// 获取项目列表信息
|
||||
getList() {
|
||||
this.listLoading = true;
|
||||
this.listLoading = true
|
||||
getTrialToBeDoneList(this.searchData)
|
||||
.then((res) => {
|
||||
this.list = res.Result.CurrentPageData;
|
||||
this.total = res.Result.TotalCount;
|
||||
this.listLoading = false;
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
this.listLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.listLoading = false;
|
||||
});
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
// 查询
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1;
|
||||
this.getList();
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 查询
|
||||
handleSelectSearch() {
|
||||
this.searchData.PageIndex = 1;
|
||||
this.getList();
|
||||
this.isShow = false;
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
this.isShow = false
|
||||
},
|
||||
// 重置
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault();
|
||||
this.getList();
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 新增项目
|
||||
handleNew() {
|
||||
// this.$router.push({ name: 'CreateTrial' })
|
||||
this.title = this.$t("trials:trials-list:dialogTitle:new");
|
||||
this.currentId = "";
|
||||
this.dialogVisible = true;
|
||||
this.title = this.$t('trials:trials-list:dialogTitle:new')
|
||||
this.currentId = ''
|
||||
this.dialogVisible = true
|
||||
},
|
||||
// 编辑项目
|
||||
handleEdit(row) {
|
||||
this.title = this.$t("trials:trials-list:dialogTitle:edit");
|
||||
this.currentId = row.Id;
|
||||
this.dialogVisible = true;
|
||||
this.title = this.$t('trials:trials-list:dialogTitle:edit')
|
||||
this.currentId = row.Id
|
||||
this.dialogVisible = true
|
||||
},
|
||||
handleCommission(row) {
|
||||
this.doneTitle = this.$t("trials:trials-list:dialogTitle:doneTitle");
|
||||
this.currentId = row.Id;
|
||||
this.doneDialogVisible = true;
|
||||
this.doneTitle = this.$t('trials:trials-list:dialogTitle:doneTitle')
|
||||
this.currentId = row.Id
|
||||
this.doneDialogVisible = true
|
||||
},
|
||||
closeDialog() {
|
||||
this.dialogVisible = false;
|
||||
this.dialogVisible = false
|
||||
},
|
||||
// 状态
|
||||
handleStatus(row) {
|
||||
if (row.TrialStatusStr === "Initializing") {
|
||||
this.listLoading = true;
|
||||
if (row.TrialStatusStr === 'Initializing') {
|
||||
this.listLoading = true
|
||||
ifTrialCanOngoing(row.Id)
|
||||
.then((res) => {
|
||||
this.listLoading = false;
|
||||
this.listLoading = false
|
||||
if (res.Result) {
|
||||
this.currentRow = { ...row };
|
||||
this.statusVisible = true;
|
||||
this.currentRow = { ...row }
|
||||
this.statusVisible = true
|
||||
} else {
|
||||
this.$confirm(res.ErrorMessage, {
|
||||
type: "warning",
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: (action) => {},
|
||||
});
|
||||
callback: (action) => {}
|
||||
})
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.listLoading = false;
|
||||
});
|
||||
this.listLoading = false
|
||||
})
|
||||
} else {
|
||||
this.currentRow = { ...row };
|
||||
this.statusVisible = true;
|
||||
this.currentRow = { ...row }
|
||||
this.statusVisible = true
|
||||
}
|
||||
},
|
||||
closeStatusDialog() {
|
||||
this.statusVisible = false;
|
||||
this.statusVisible = false
|
||||
},
|
||||
// 废除
|
||||
handleAbandon(row) {
|
||||
this.$confirm(this.$t("trials:trials-list:message:abolition"), {
|
||||
type: "warning",
|
||||
distinguishCancelAndClose: true,
|
||||
this.$confirm(this.$t('trials:trials-list:message:abolition'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
this.currentRow = { ...row };
|
||||
this.abandonTrial();
|
||||
this.currentRow = { ...row }
|
||||
this.abandonTrial()
|
||||
})
|
||||
.catch(() => {});
|
||||
.catch(() => {})
|
||||
},
|
||||
// 废除项目
|
||||
abandonTrial() {
|
||||
this.listLoading = true;
|
||||
this.listLoading = true
|
||||
abandonTrial(this.currentRow.Id, true)
|
||||
.then((res) => {
|
||||
this.listLoading = false;
|
||||
this.listLoading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList();
|
||||
this.getList()
|
||||
this.$message.success(
|
||||
this.$t("trials:trials-list:message:abolitionSuccessfully")
|
||||
);
|
||||
this.$t('trials:trials-list:message:abolitionSuccessfully')
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.listLoading = false;
|
||||
});
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
rowClick(row, col) {
|
||||
if (
|
||||
(row.TrialStatusStr === "Initializing" &&
|
||||
!this.hasPermi(["role:pm"])) ||
|
||||
row.IsDeleted
|
||||
)
|
||||
return;
|
||||
if ((row.TrialStatusStr === 'Initializing' && !this.hasPermi(['role:pm'])) || row.IsDeleted) {
|
||||
return
|
||||
} else if ((row.TrialStatusStr === 'Completed' || row.TrialStatusStr === 'Stopped') && !(this.hasPermi(['role:qa']) || this.hasPermi(['role:ea']) || this.hasPermi(['role:pm']))) {
|
||||
return
|
||||
}
|
||||
this.$router.push({
|
||||
path: `/trials/trials-panel?trialId=${row.Id}&trialCode=${row.TrialCode}&researchProgramNo=${row.ResearchProgramNo}`,
|
||||
});
|
||||
path: `/trials/trials-panel?trialId=${row.Id}&trialCode=${row.TrialCode}&researchProgramNo=${row.ResearchProgramNo}`
|
||||
})
|
||||
},
|
||||
// panel
|
||||
handleDetail(row) {
|
||||
this.$router.push({
|
||||
path: `/trials/trials-panel?trialId=${row.Id}&trialCode=${row.TrialCode}&researchProgramNo=${row.ResearchProgramNo}`,
|
||||
});
|
||||
path: `/trials/trials-panel?trialId=${row.Id}&trialCode=${row.TrialCode}&researchProgramNo=${row.ResearchProgramNo}`
|
||||
})
|
||||
},
|
||||
// 获取已勾选行数据
|
||||
handleSelectChange(val) {
|
||||
const arr = [];
|
||||
const arr = []
|
||||
for (let index = 0; index < val.length; index++) {
|
||||
arr.push(val[index]);
|
||||
arr.push(val[index])
|
||||
}
|
||||
this.selectArr = arr;
|
||||
this.selectArr = arr
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(column) {
|
||||
if (column.order === "ascending") {
|
||||
this.searchData.Asc = true;
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false;
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
if (column.prop === "Criterion") {
|
||||
this.searchData.SortField = "CriterionId";
|
||||
if (column.prop === 'Criterion') {
|
||||
this.searchData.SortField = 'CriterionId'
|
||||
} else {
|
||||
this.searchData.SortField = column.prop;
|
||||
this.searchData.SortField = column.prop
|
||||
}
|
||||
this.searchData.PageIndex = 1;
|
||||
this.getList();
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 导出Excel表格
|
||||
handleExportTrial() {
|
||||
this.exportLoading = true;
|
||||
let data = {
|
||||
...this.searchData,
|
||||
};
|
||||
data.TrialIdList = this.selectArr.map((item) => item.Id);
|
||||
this.exportLoading = true
|
||||
const data = {
|
||||
...this.searchData
|
||||
}
|
||||
data.TrialIdList = this.selectArr.map((item) => item.Id)
|
||||
return getTrialList_Export(data)
|
||||
.then((res) => {
|
||||
this.exportLoading = false;
|
||||
this.exportLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.exportLoading = false;
|
||||
});
|
||||
this.selectArr.forEach((element, index) => {
|
||||
// element.ExpeditedStr = element.Expedited === 0 ? 'No' : element.Expedited === 1 ? '24H' : '48H'
|
||||
// element.ModalityListStr = element.ModalityList.join(', ')
|
||||
// element.CreateTimeStr = element.CreateTime
|
||||
// element.Criterion = element.CriterionList.join(', ')
|
||||
element.Deleted = element.IsDeleted ? "Yes" : "No";
|
||||
element.Index = index + 1;
|
||||
});
|
||||
var workbook = new Excel.Workbook();
|
||||
var sheet = workbook.addWorksheet("Trials");
|
||||
|
||||
sheet.properties.defaultRowHeight = 22;
|
||||
// sheet.columns = [
|
||||
// { key: 'Index', width: 5 },
|
||||
// { key: 'Code', width: 15 },
|
||||
// { key: 'ExpeditedStr', width: 13 },
|
||||
// { key: 'TrialStatusStr', width: 10 },
|
||||
// { key: 'Indication', width: 25 },
|
||||
// { key: 'Phase', width: 10 },
|
||||
// { key: 'ReviewType', width: 20 },
|
||||
// { key: 'Criterion', width: 15 },
|
||||
// { key: 'ModalityListStr', width: 30 },
|
||||
// { key: 'CRO', width: 10 },
|
||||
// { key: 'Sponsor', width: 20 },
|
||||
// { key: 'CreateTimeStr', width: 18 }
|
||||
// ]
|
||||
sheet.columns = [
|
||||
{ key: "Index", width: 5 },
|
||||
{ key: "TrialCode", width: 25 },
|
||||
{ key: "ExperimentName", width: 25 },
|
||||
{ key: "ResearchProgramNo", width: 25 },
|
||||
{ key: "Sponsor", width: 25 },
|
||||
{ key: "Deleted", width: 10 },
|
||||
{ key: "CreateTime", width: 25 },
|
||||
];
|
||||
|
||||
// 处理标题
|
||||
sheet.mergeCells("A1", "G2");
|
||||
sheet.getCell("A1").value = "Trials";
|
||||
sheet.getCell("A1").alignment = {
|
||||
vertical: "middle",
|
||||
horizontal: "center",
|
||||
};
|
||||
sheet.getCell("A1").font = {
|
||||
name: "SimSun",
|
||||
family: 4,
|
||||
size: 13,
|
||||
bold: true,
|
||||
};
|
||||
sheet.mergeCells("A3", "G3");
|
||||
var now = new Date();
|
||||
sheet.getCell("A3").value = now.toLocaleDateString();
|
||||
sheet.getCell("A3").alignment = {
|
||||
vertical: "middle",
|
||||
horizontal: "right",
|
||||
};
|
||||
|
||||
sheet.getRow(4).values = [
|
||||
"NO.",
|
||||
"Trial ID",
|
||||
"试验名称",
|
||||
"研究方案号",
|
||||
"申办方",
|
||||
"是否废除",
|
||||
"Date Created",
|
||||
];
|
||||
sheet.getRow(4).font = {
|
||||
name: "SimSun",
|
||||
family: 4,
|
||||
size: 11,
|
||||
bold: true,
|
||||
};
|
||||
sheet.getRow(4).alignment = { vertical: "middle", horizontal: "left" };
|
||||
|
||||
sheet.addRows(this.selectArr);
|
||||
|
||||
sheet.eachRow((row, number) => {
|
||||
if (number > 3) {
|
||||
row.eachCell((cell, rowNumber) => {
|
||||
cell.alignment = { vertical: "center", horizontal: "left" };
|
||||
cell.border = {
|
||||
top: { style: "thin" },
|
||||
left: { style: "thin" },
|
||||
bottom: { style: "thin" },
|
||||
right: { style: "thin" },
|
||||
};
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
workbook.xlsx
|
||||
.writeBuffer({
|
||||
base64: true,
|
||||
this.exportLoading = false
|
||||
})
|
||||
.then(function (xls64) {
|
||||
var data = new Blob([xls64], {
|
||||
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
});
|
||||
|
||||
if ("msSaveOrOpenBlob" in navigator) {
|
||||
// ie使用的下载方式
|
||||
window.navigator.msSaveOrOpenBlob(data, "Trials" + ".xlsx");
|
||||
} else {
|
||||
var a = document.createElement("a");
|
||||
|
||||
var url = URL.createObjectURL(data);
|
||||
a.href = url;
|
||||
a.download = "Trials" + ".xlsx";
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
setTimeout(function () {
|
||||
document.body.removeChild(a);
|
||||
window.URL.revokeObjectURL(url);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -54,8 +54,8 @@
|
||||
j.armEnum === 1
|
||||
? $t('trials:adReview:table:viewR1')
|
||||
: j.armEnum === 2
|
||||
? $t('trials:adReview:table:viewR2')
|
||||
: $fd('ArmEnum', j.armEnum)
|
||||
? $t('trials:adReview:table:viewR2')
|
||||
: $fd('ArmEnum', j.armEnum)
|
||||
"
|
||||
align="center"
|
||||
prop=""
|
||||
@@ -81,18 +81,17 @@
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.DictionaryCode
|
||||
"
|
||||
>{{
|
||||
$fd(
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[
|
||||
i
|
||||
].DictionaryCode,
|
||||
parseInt(
|
||||
scope.row.VisitTaskInfoList[j.index]
|
||||
.JudgeQuestionList[i].Answer
|
||||
)
|
||||
>{{
|
||||
$fd(
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[
|
||||
i
|
||||
].DictionaryCode,
|
||||
parseInt(
|
||||
scope.row.VisitTaskInfoList[j.index]
|
||||
.JudgeQuestionList[i].Answer
|
||||
)
|
||||
}}</span
|
||||
>
|
||||
)
|
||||
}}</span>
|
||||
<span v-else>{{
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.Answer
|
||||
@@ -321,7 +320,7 @@
|
||||
alt=""
|
||||
crossorigin="anonymous"
|
||||
style="max-width: 100%; max-height: 100%"
|
||||
/>
|
||||
>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@@ -435,88 +434,87 @@ import {
|
||||
// uploadJudgeTaskImage,
|
||||
saveJudgeVisitTaskResult,
|
||||
submitJudgeVisitTaskResult,
|
||||
getReadingPastResultList,
|
||||
} from "@/api/trials";
|
||||
import { getAutoCutNextTask } from "@/api/user";
|
||||
import { setSkipReadingCache } from "@/api/reading";
|
||||
import const_ from "@/const/sign-code";
|
||||
import { getToken } from "@/utils/auth";
|
||||
import SignForm from "@/views/trials/components/newSignForm";
|
||||
import DicomEvent from "@/views/trials/trials-panel/reading/dicoms/components/DicomEvent";
|
||||
getReadingPastResultList
|
||||
} from '@/api/trials'
|
||||
import { getAutoCutNextTask } from '@/api/user'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import const_ from '@/const/sign-code'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
// import store from '@/store'
|
||||
import { changeURLStatic } from "@/utils/history.js";
|
||||
import Viewer from "v-viewer";
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
export default {
|
||||
name: "AdReview",
|
||||
name: 'AdReview',
|
||||
components: { SignForm },
|
||||
props: {
|
||||
trialId: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
subjectId: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
readingCategory: {
|
||||
type: Number,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
subjectCode: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
taskBlindName: {
|
||||
type: String,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
isReadingShowPreviousResults: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
required: true
|
||||
},
|
||||
isExistsClinicalData: {
|
||||
type: Boolean,
|
||||
required: true,
|
||||
},
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
adInfo: {},
|
||||
judgeQuestion: [],
|
||||
adForm: {
|
||||
visitTaskId: "",
|
||||
judgeResultTaskId: "",
|
||||
judgeResultRemark: "",
|
||||
visitTaskId: '',
|
||||
judgeResultTaskId: '',
|
||||
judgeResultRemark: '',
|
||||
// judgeResultImagePath: ''
|
||||
judgeResultImagePathList: [],
|
||||
judgeResultImagePathList: []
|
||||
},
|
||||
currentUser: zzSessionStorage.getItem("userName"),
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
accept: ".png,.jpg,.jpeg",
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: "",
|
||||
imageUrl: '',
|
||||
uploadDisabled: false,
|
||||
fileList: [],
|
||||
loading: false,
|
||||
visitTaskArmList: [],
|
||||
priorADList: [],
|
||||
priorLoading: false,
|
||||
judgeResultArmEnum: "",
|
||||
judgeResultArmEnum: '',
|
||||
criterionType: null,
|
||||
openWindow: null,
|
||||
isFixed: false,
|
||||
images: [],
|
||||
remark: "",
|
||||
};
|
||||
remark: ''
|
||||
}
|
||||
},
|
||||
// watch: {
|
||||
// visitTaskId: {
|
||||
@@ -532,261 +530,260 @@ export default {
|
||||
// }
|
||||
// },
|
||||
mounted() {
|
||||
this.initializeViewer();
|
||||
this.criterionType = parseInt(this.$route.query.criterionType);
|
||||
this.getAdInfo();
|
||||
this.criterionType = parseInt(this.$route.query.criterionType)
|
||||
this.getAdInfo()
|
||||
if (this.isReadingShowPreviousResults) {
|
||||
this.getPriorAdList();
|
||||
this.getPriorAdList()
|
||||
}
|
||||
DicomEvent.$on("resetOpenWindow", () => {
|
||||
DicomEvent.$on('resetOpenWindow', () => {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close();
|
||||
this.openWindow.close()
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off("resetOpenWindow");
|
||||
DicomEvent.$off('resetOpenWindow')
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close();
|
||||
this.openWindow.close()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
async getAdInfo() {
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
try {
|
||||
const res = await getJudgeReadingInfo({
|
||||
visitTaskId: this.visitTaskId,
|
||||
});
|
||||
visitTaskId: this.visitTaskId
|
||||
})
|
||||
if (res.IsSuccess) {
|
||||
var judgeQS = [];
|
||||
var judgeQS = []
|
||||
if (res.Result.VisitInfoList.length > 0) {
|
||||
res.Result.VisitInfoList[0].VisitTaskInfoList.map((v, index) => {
|
||||
var qsObj = {
|
||||
armEnum: v.ArmEnum,
|
||||
judgeQuestionList: [],
|
||||
index: index,
|
||||
};
|
||||
index: index
|
||||
}
|
||||
v.JudgeQuestionList.map((q) => {
|
||||
if (q.QuestionType === 1) {
|
||||
qsObj.judgeQuestionList.push(q.QuestionName);
|
||||
qsObj.judgeQuestionList.push(q.QuestionName)
|
||||
} else if (q.QuestionType === 3 && this.criterionType === 10) {
|
||||
qsObj.judgeQuestionList.push(
|
||||
this.$t("trials:globalReview:table:visitRemark")
|
||||
);
|
||||
this.$t('trials:globalReview:table:visitRemark')
|
||||
)
|
||||
} else {
|
||||
qsObj.judgeQuestionList.push(
|
||||
this.$fd("JudgeReadingQuestionType", q.QuestionType)
|
||||
);
|
||||
this.$fd('JudgeReadingQuestionType', q.QuestionType)
|
||||
)
|
||||
}
|
||||
});
|
||||
judgeQS.push(qsObj);
|
||||
});
|
||||
})
|
||||
judgeQS.push(qsObj)
|
||||
})
|
||||
}
|
||||
this.judgeQuestion = judgeQS;
|
||||
this.judgeQuestion = judgeQS
|
||||
this.isFixed =
|
||||
this.judgeQuestion.length > 0 &&
|
||||
this.judgeQuestion[0].judgeQuestionList.length > 4;
|
||||
this.adInfo = res.Result;
|
||||
this.adForm.judgeResultTaskId = res.Result.JudgeResultTaskId;
|
||||
this.judgeQuestion[0].judgeQuestionList.length > 4
|
||||
this.adInfo = res.Result
|
||||
this.adForm.judgeResultTaskId = res.Result.JudgeResultTaskId
|
||||
|
||||
this.fileList = [];
|
||||
this.fileList = []
|
||||
if (res.Result.JudgeResultImagePathList) {
|
||||
res.Result.JudgeResultImagePathList.map((url) => {
|
||||
if (url) {
|
||||
this.fileList.push({ name: "", url: url });
|
||||
this.fileList.push({ name: '', url: url })
|
||||
}
|
||||
});
|
||||
})
|
||||
this.adForm.judgeResultImagePathList =
|
||||
res.Result.JudgeResultImagePathList;
|
||||
res.Result.JudgeResultImagePathList
|
||||
}
|
||||
this.visitTaskArmList = res.Result.VisitTaskArmList;
|
||||
this.visitTaskArmList = res.Result.VisitTaskArmList
|
||||
var i = this.visitTaskArmList.findIndex(
|
||||
(i) => i.VisitTaskId === this.adForm.judgeResultTaskId
|
||||
);
|
||||
)
|
||||
if (i > -1) {
|
||||
// 本人已完整查看两位独立阅片人的全部相关影像和评估数据,经过综合研判,更认同第一阅片人(R1)对该病例的整体评估,原因是:
|
||||
this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum;
|
||||
var msg = "";
|
||||
this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum
|
||||
var msg = ''
|
||||
if (this.judgeResultArmEnum === 1) {
|
||||
msg = this.$t("trials:adReview:title:msg1");
|
||||
msg = this.$t('trials:adReview:title:msg1')
|
||||
} else if (this.judgeResultArmEnum === 2) {
|
||||
msg = this.$t("trials:adReview:title:msg3");
|
||||
msg = this.$t('trials:adReview:title:msg3')
|
||||
}
|
||||
this.remark = msg;
|
||||
this.adForm.judgeResultRemark = res.Result.JudgeResultRemark;
|
||||
this.remark = msg
|
||||
this.adForm.judgeResultRemark = res.Result.JudgeResultRemark
|
||||
}
|
||||
}
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async getPriorAdList() {
|
||||
this.priorLoading = true;
|
||||
this.priorLoading = true
|
||||
try {
|
||||
const res = await getReadingPastResultList({
|
||||
visitTaskId: this.visitTaskId,
|
||||
});
|
||||
visitTaskId: this.visitTaskId
|
||||
})
|
||||
if (res.IsSuccess) {
|
||||
this.priorADList = res.Result;
|
||||
this.priorADList = res.Result
|
||||
}
|
||||
this.priorLoading = false;
|
||||
this.priorLoading = false
|
||||
} catch (e) {
|
||||
this.priorLoading = false;
|
||||
this.priorLoading = false
|
||||
}
|
||||
},
|
||||
handleVisitTaskArmChange(v) {
|
||||
var i = this.visitTaskArmList.findIndex((i) => i.VisitTaskId === v);
|
||||
var i = this.visitTaskArmList.findIndex((i) => i.VisitTaskId === v)
|
||||
if (i > -1) {
|
||||
// 本人已完整查看两位独立阅片人的全部相关影像和评估数据,经过综合研判,更认同第一阅片人(R1)对该病例的整体评估,原因是:
|
||||
this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum;
|
||||
var msg = "";
|
||||
this.judgeResultArmEnum = this.visitTaskArmList[i].ArmEnum
|
||||
var msg = ''
|
||||
if (this.judgeResultArmEnum === 1) {
|
||||
msg = this.$t("trials:adReview:title:msg1");
|
||||
msg = this.$t('trials:adReview:title:msg1')
|
||||
} else {
|
||||
msg = this.$t("trials:adReview:title:msg3");
|
||||
msg = this.$t('trials:adReview:title:msg3')
|
||||
}
|
||||
// this.adForm.judgeResultRemark = `本人已完整查看两位独立阅片人的全部相关影像和评估数据,经过综合研判,更认同${this.$fd('ArmEnum', this.judgeResultArmEnum)}对该病例的整体评估,原因是:`
|
||||
this.remark = msg;
|
||||
this.adForm.judgeResultRemark = "";
|
||||
this.remark = msg
|
||||
this.adForm.judgeResultRemark = ''
|
||||
} else {
|
||||
this.judgeResultArmEnum = "";
|
||||
this.remark = "";
|
||||
this.adForm.judgeResultRemark = "";
|
||||
this.judgeResultArmEnum = ''
|
||||
this.remark = ''
|
||||
this.adForm.judgeResultRemark = ''
|
||||
}
|
||||
},
|
||||
previewCD() {
|
||||
var token = getToken();
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/clinicalData?subjectId=${this.subjectId}&trialId=${this.trialId}&visitTaskId=${this.visitTaskId}&TokenKey=${token}`,
|
||||
});
|
||||
window.open(routeData.href, "_blank");
|
||||
path: `/clinicalData?subjectId=${this.subjectId}&trialId=${this.trialId}&visitTaskId=${this.visitTaskId}&TokenKey=${token}`
|
||||
})
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
async handleSave() {
|
||||
const valid = await this.$refs["adForm"].validate();
|
||||
if (!valid) return;
|
||||
this.loading = true;
|
||||
var paths = [];
|
||||
const valid = await this.$refs['adForm'].validate()
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
var paths = []
|
||||
this.fileList.map((file) => {
|
||||
if (file.url) {
|
||||
paths.push(file.url);
|
||||
paths.push(file.url)
|
||||
}
|
||||
});
|
||||
this.adForm.judgeResultImagePathList = paths;
|
||||
this.adForm.visitTaskId = this.visitTaskId;
|
||||
})
|
||||
this.adForm.judgeResultImagePathList = paths
|
||||
this.adForm.visitTaskId = this.visitTaskId
|
||||
try {
|
||||
await saveJudgeVisitTaskResult(this.adForm);
|
||||
this.$message.success(this.$t("common:message:savedSuccessfully"));
|
||||
this.loading = false;
|
||||
await saveJudgeVisitTaskResult(this.adForm)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async handleSubmit() {
|
||||
const valid = await this.$refs["adForm"].validate();
|
||||
if (!valid) return;
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature;
|
||||
this.signCode = ImageAssessmentReportConfirmation;
|
||||
this.signVisible = true;
|
||||
const valid = await this.$refs['adForm'].validate()
|
||||
if (!valid) return
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo);
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false;
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
async signConfirm(signInfo) {
|
||||
this.loading = true;
|
||||
var paths = [];
|
||||
this.loading = true
|
||||
var paths = []
|
||||
this.fileList.map((file) => {
|
||||
paths.push(file.url);
|
||||
});
|
||||
paths.push(file.url)
|
||||
})
|
||||
var params = {
|
||||
data: {
|
||||
visitTaskId: this.visitTaskId,
|
||||
judgeResultTaskId: this.adForm.judgeResultTaskId,
|
||||
judgeResultRemark: this.adForm.judgeResultRemark,
|
||||
judgeResultImagePathList: paths,
|
||||
judgeResultImagePathList: paths
|
||||
},
|
||||
signInfo: signInfo,
|
||||
};
|
||||
signInfo: signInfo
|
||||
}
|
||||
try {
|
||||
const res = await submitJudgeVisitTaskResult(params);
|
||||
const res = await submitJudgeVisitTaskResult(params)
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t("common:message:savedSuccessfully"));
|
||||
this.isEdit = false;
|
||||
this.$refs["signForm"].btnLoading = false;
|
||||
this.signVisible = false;
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.isEdit = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
this.signVisible = false
|
||||
// window.location.reload()
|
||||
// window.opener.postMessage('refreshTaskList', window.location)
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.adInfo.ReadingTaskState = 2;
|
||||
const res = await getAutoCutNextTask();
|
||||
var isAutoTask = res.Result.AutoCutNextTask;
|
||||
this.adInfo.ReadingTaskState = 2
|
||||
const res = await getAutoCutNextTask()
|
||||
var isAutoTask = res.Result.AutoCutNextTask
|
||||
if (isAutoTask) {
|
||||
// store.dispatch('reading/resetVisitTasks')
|
||||
window.location.reload();
|
||||
window.location.reload()
|
||||
} else {
|
||||
// '当前阅片任务已完成,是否进入下一个阅片任务?'
|
||||
const confirm = await this.$confirm(
|
||||
this.$t("trials:adReview:title:msg2"),
|
||||
this.$t('trials:adReview:title:msg2'),
|
||||
{
|
||||
type: "warning",
|
||||
distinguishCancelAndClose: true,
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
);
|
||||
if (confirm === "confirm") {
|
||||
)
|
||||
if (confirm === 'confirm') {
|
||||
// store.dispatch('reading/resetVisitTasks')
|
||||
// DicomEvent.$emit('getNextTask')
|
||||
window.location.reload();
|
||||
window.location.reload()
|
||||
} else {
|
||||
changeURLStatic("visitTaskId", this.visitTaskId);
|
||||
changeURLStatic('visitTaskId', this.visitTaskId)
|
||||
}
|
||||
}
|
||||
window.opener.postMessage("refreshTaskList", window.location);
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
}
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false;
|
||||
this.$refs["signForm"].btnLoading = false;
|
||||
this.loading = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
},
|
||||
handleViewDetail(visitTaskId) {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close();
|
||||
this.openWindow.close()
|
||||
}
|
||||
var token = getToken();
|
||||
var criterionType = parseInt(localStorage.getItem("CriterionType"));
|
||||
var readingTool = this.$router.currentRoute.query.readingTool;
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool);
|
||||
var token = getToken()
|
||||
var criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||
var isReadingTaskViewInOrder =
|
||||
this.$router.currentRoute.query.isReadingTaskViewInOrder;
|
||||
this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId =
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId;
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
|
||||
var path = "";
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||
this.subjectId
|
||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||
this.subjectId
|
||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
}
|
||||
var routeData = this.$router.resolve({ path });
|
||||
this.openWindow = window.open(routeData.href, "_blank");
|
||||
var routeData = this.$router.resolve({ path })
|
||||
this.openWindow = window.open(routeData.href, '_blank')
|
||||
},
|
||||
handleView(row, armEnum) {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close();
|
||||
this.openWindow.close()
|
||||
}
|
||||
// var token = getToken()
|
||||
// var task = row.VisitTaskInfoList.find(item => item.ArmEnum === armEnum)
|
||||
@@ -794,17 +791,17 @@ export default {
|
||||
// path: `/readingPage?trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&TokenKey=${token}&isReadingShowPreviousResults=false`
|
||||
// })
|
||||
// window.open(routeData.href, '_blank')
|
||||
var token = getToken();
|
||||
var task = row.VisitTaskInfoList.find((item) => item.ArmEnum === armEnum);
|
||||
var criterionType = this.$router.currentRoute.query.criterionType;
|
||||
var readingTool = this.$router.currentRoute.query.readingTool;
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool);
|
||||
var token = getToken()
|
||||
var task = row.VisitTaskInfoList.find((item) => item.ArmEnum === armEnum)
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||
var isReadingTaskViewInOrder =
|
||||
this.$router.currentRoute.query.isReadingTaskViewInOrder;
|
||||
this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId =
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId;
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
|
||||
var path = "";
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
@@ -812,7 +809,7 @@ export default {
|
||||
this.subjectId
|
||||
}&visitTaskId=${
|
||||
task.VisitTaskId
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
@@ -820,26 +817,26 @@ export default {
|
||||
this.subjectId
|
||||
}&visitTaskId=${
|
||||
task.VisitTaskId
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
}
|
||||
var routeData = this.$router.resolve({ path });
|
||||
this.openWindow = window.open(routeData.href, "_blank");
|
||||
var routeData = this.$router.resolve({ path })
|
||||
this.openWindow = window.open(routeData.href, '_blank')
|
||||
},
|
||||
handleViewGl(row, armEnum) {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close();
|
||||
this.openWindow.close()
|
||||
}
|
||||
var token = getToken();
|
||||
var task = row.VisitTaskInfoList.find((item) => item.ArmEnum === armEnum);
|
||||
var criterionType = this.$router.currentRoute.query.criterionType;
|
||||
var readingTool = this.$router.currentRoute.query.readingTool;
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool);
|
||||
var token = getToken()
|
||||
var task = row.VisitTaskInfoList.find((item) => item.ArmEnum === armEnum)
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||
var isReadingTaskViewInOrder =
|
||||
this.$router.currentRoute.query.isReadingTaskViewInOrder;
|
||||
this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId =
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId;
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
|
||||
var path = "";
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
@@ -847,7 +844,7 @@ export default {
|
||||
this.subjectId
|
||||
}&visitTaskId=${
|
||||
task.GlobalVisitTaskId
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
@@ -855,10 +852,10 @@ export default {
|
||||
this.subjectId
|
||||
}&visitTaskId=${
|
||||
task.GlobalVisitTaskId
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
}
|
||||
var routeData = this.$router.resolve({ path });
|
||||
this.openWindow = window.open(routeData.href, "_blank");
|
||||
var routeData = this.$router.resolve({ path })
|
||||
this.openWindow = window.open(routeData.href, '_blank')
|
||||
},
|
||||
// uploadScreenshot(param) {
|
||||
// this.loading = true
|
||||
@@ -876,105 +873,93 @@ export default {
|
||||
// })
|
||||
// },
|
||||
async uploadScreenshot(param) {
|
||||
this.loading = true;
|
||||
this.uploadDisabled = false;
|
||||
var trialId = this.$route.query.trialId;
|
||||
var file = await this.fileToBlob(param.file);
|
||||
this.loading = true
|
||||
this.uploadDisabled = false
|
||||
var trialId = this.$route.query.trialId
|
||||
var file = await this.fileToBlob(param.file)
|
||||
const res = await this.OSSclient.put(
|
||||
`/${trialId}/Read/${this.subjectId}/visit/${param.file.name}`,
|
||||
file
|
||||
);
|
||||
console.log(res);
|
||||
)
|
||||
console.log(res)
|
||||
this.fileList.push({
|
||||
name: param.file.name,
|
||||
url: this.$getObjectName(res.url),
|
||||
});
|
||||
this.loading = false;
|
||||
this.uploadDisabled = true;
|
||||
url: this.$getObjectName(res.url)
|
||||
})
|
||||
this.loading = false
|
||||
this.uploadDisabled = true
|
||||
},
|
||||
handleBeforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
return true;
|
||||
return true
|
||||
} else {
|
||||
const msg = this.$t("trials:adReview:title:msg4").replace(
|
||||
"xxx",
|
||||
const msg = this.$t('trials:adReview:title:msg4').replace(
|
||||
'xxx',
|
||||
this.accept
|
||||
);
|
||||
this.$alert(msg);
|
||||
return false;
|
||||
)
|
||||
this.$alert(msg)
|
||||
return false
|
||||
}
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var index = fileName.lastIndexOf(".");
|
||||
var suffix = fileName.substring(index + 1, fileName.length);
|
||||
var index = fileName.lastIndexOf('.')
|
||||
var suffix = fileName.substring(index + 1, fileName.length)
|
||||
if (
|
||||
this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) ===
|
||||
-1
|
||||
) {
|
||||
return false;
|
||||
return false
|
||||
} else {
|
||||
return true;
|
||||
return true
|
||||
}
|
||||
},
|
||||
// 图片清空
|
||||
removeImage() {
|
||||
this.imageUrl = "";
|
||||
this.fileList = [];
|
||||
this.adForm.judgeResultImagePath = "";
|
||||
this.imageUrl = ''
|
||||
this.fileList = []
|
||||
this.adForm.judgeResultImagePath = ''
|
||||
},
|
||||
// 预览图片
|
||||
handlePictureCardPreview(file) {
|
||||
this.images = this.fileList.map(
|
||||
(f) => this.OSSclientConfig.basePath + f.url
|
||||
);
|
||||
)
|
||||
// this.imageUrl = this.OSSclientConfig.basePath + file.url
|
||||
this.$refs[file.url].$viewer.show();
|
||||
this.$refs[file.url].$viewer.show()
|
||||
},
|
||||
// 删除图片
|
||||
handleRemove(file, fileList) {
|
||||
var idx = this.fileList.findIndex((i) => i.url === file.url);
|
||||
if (idx === -1) return;
|
||||
this.fileList.splice(idx, 1);
|
||||
var idx = this.fileList.findIndex((i) => i.url === file.url)
|
||||
if (idx === -1) return
|
||||
this.fileList.splice(idx, 1)
|
||||
},
|
||||
async skipTask() {
|
||||
try {
|
||||
// 是否确认跳过?
|
||||
const confirm = await this.$confirm(
|
||||
this.$t("trials:readingReport:message:skipConfirm"),
|
||||
this.$t('trials:readingReport:message:skipConfirm'),
|
||||
{
|
||||
type: "warning",
|
||||
distinguishCancelAndClose: true,
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
);
|
||||
if (confirm !== "confirm") return;
|
||||
this.loading = true;
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
this.loading = true
|
||||
const res = await setSkipReadingCache({
|
||||
visitTaskId: this.visitTaskId,
|
||||
});
|
||||
this.loading = false;
|
||||
visitTaskId: this.visitTaskId
|
||||
})
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
window.location.reload();
|
||||
window.location.reload()
|
||||
}
|
||||
} catch (e) {
|
||||
this.loading = false;
|
||||
console.log(e);
|
||||
this.loading = false
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
initializeViewer() {
|
||||
Viewer.setDefaults({
|
||||
toolbar: {
|
||||
zoomIn: true,
|
||||
zoomOut: true,
|
||||
rotateLeft: true,
|
||||
rotateRight: true,
|
||||
flipHorizontal: true,
|
||||
flipVertical: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.adReview_wrapper {
|
||||
|
||||
@@ -276,7 +276,6 @@ import { submitTableQuestion, deleteReadingRowAnswer, getIsSuvMaxLesion } from '
|
||||
// import { uploadPrintscreen } from '@/api/reading'
|
||||
import DicomEvent from './../DicomEvent'
|
||||
import store from '@/store'
|
||||
import Viewer from 'v-viewer'
|
||||
export default {
|
||||
name: 'MeasurementForm',
|
||||
props: {
|
||||
@@ -353,7 +352,6 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initializeViewer()
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.initForm()
|
||||
DicomEvent.$on('handleImageQualityAbnormal', () => {
|
||||
@@ -380,11 +378,6 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
initializeViewer() {
|
||||
Viewer.setDefaults({
|
||||
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true }
|
||||
})
|
||||
},
|
||||
previewImage() {
|
||||
this.$refs.viewer[0].$viewer.show()
|
||||
},
|
||||
|
||||
+18
-2
@@ -239,7 +239,7 @@
|
||||
<!-- </span>-->
|
||||
<!-- </div>-->
|
||||
</el-upload>
|
||||
<el-dialog
|
||||
<!-- <el-dialog
|
||||
v-if="question.Type==='upload'"
|
||||
append-to-body
|
||||
:visible.sync="imgVisible"
|
||||
@@ -250,7 +250,20 @@
|
||||
加载中<span class="dot">...</span>
|
||||
</div>
|
||||
</el-image>
|
||||
</el-dialog>
|
||||
</el-dialog> -->
|
||||
<viewer
|
||||
v-if="question.Type==='upload' && imgVisible"
|
||||
:ref="imageUrl"
|
||||
style="margin:0 10px;"
|
||||
:images="[imageUrl]"
|
||||
>
|
||||
<img
|
||||
v-show="false"
|
||||
crossorigin="anonymous"
|
||||
:src="imageUrl"
|
||||
alt="Image"
|
||||
>
|
||||
</viewer>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
@@ -801,6 +814,9 @@ export default {
|
||||
}else{
|
||||
this.imageUrl = this.OSSclientConfig.basePath + file.url
|
||||
this.imgVisible = true
|
||||
this.$nextTick(()=>{
|
||||
this.$refs[this.imageUrl].$viewer.show()
|
||||
})
|
||||
}
|
||||
},
|
||||
// 删除图片
|
||||
|
||||
@@ -138,27 +138,41 @@
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
alt=""
|
||||
<viewer
|
||||
:ref="file.url"
|
||||
:images="[imageUrl]"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
"
|
||||
>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
crossOrigin="anonymous"
|
||||
alt=""
|
||||
style="max-width: 100%; max-height: 100%"
|
||||
/>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</viewer>
|
||||
</div>
|
||||
</el-upload>
|
||||
<el-dialog
|
||||
@@ -308,7 +322,7 @@ export default {
|
||||
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
|
||||
}else{
|
||||
this.imageUrl = this.OSSclientConfig.basePath + file.url
|
||||
this.imgVisible = true
|
||||
this.$refs[file.url].$viewer.show();
|
||||
}
|
||||
},
|
||||
// 删除图片
|
||||
|
||||
+34
-19
@@ -148,27 +148,41 @@
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
alt=""
|
||||
<viewer
|
||||
:ref="file.url"
|
||||
:images="[imageUrl]"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
"
|
||||
>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
crossOrigin="anonymous"
|
||||
alt=""
|
||||
style="max-width: 100%; max-height: 100%"
|
||||
/>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
</span>
|
||||
</viewer>
|
||||
</div>
|
||||
</el-upload>
|
||||
<el-dialog
|
||||
@@ -492,7 +506,8 @@ export default {
|
||||
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
|
||||
}else{
|
||||
this.imageUrl = this.OSSclientConfig.basePath + file.url
|
||||
this.imgVisible = true
|
||||
// this.imgVisible = true
|
||||
this.$refs[file.url].$viewer.show()
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
+35
-32
@@ -14,41 +14,43 @@
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
crossOrigin="Anonymous"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
alt=""
|
||||
<viewer
|
||||
:ref="file.url"
|
||||
:images="[imageUrl]"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
"
|
||||
>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
crossOrigin="anonymous"
|
||||
alt=""
|
||||
style="max-width: 100%; max-height: 100%"
|
||||
/>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
</viewer>
|
||||
</div>
|
||||
</el-upload>
|
||||
<el-dialog
|
||||
append-to-body
|
||||
:visible.sync="imgVisible"
|
||||
width="600px"
|
||||
>
|
||||
<el-image :src="imageUrl" width="100%" crossOrigin="Anonymous">
|
||||
<div slot="placeholder" class="image-slot">
|
||||
加载中<span class="dot">...</span>
|
||||
</div>
|
||||
</el-image>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -142,7 +144,8 @@ name: "CustomizeReportPageUpload",
|
||||
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
|
||||
}else{
|
||||
this.imageUrl = this.OSSclientConfig.basePath + file.url
|
||||
this.imgVisible = true
|
||||
// this.imgVisible = true
|
||||
this.$refs[file.url].$viewer.show()
|
||||
}
|
||||
},
|
||||
// 删除图片
|
||||
|
||||
@@ -143,7 +143,6 @@ import { getMedicalReviewDialog } from '@/api/trials'
|
||||
import FeedbackForm from './FeedbackForm'
|
||||
import mimAvatar from '@/assets/MIM.png'
|
||||
import irAvatar from '@/assets/IR.png'
|
||||
import Viewer from 'v-viewer'
|
||||
export default {
|
||||
name: 'ChatForm',
|
||||
components: { FeedbackForm },
|
||||
@@ -177,7 +176,6 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initializeViewer()
|
||||
this.getMessageList()
|
||||
},
|
||||
methods: {
|
||||
@@ -213,11 +211,6 @@ export default {
|
||||
this.imagePath = `${this.OSSclientConfig.basePath}${path}`
|
||||
this.previewDialog = true
|
||||
this.$refs[path][0].$viewer.show()
|
||||
},
|
||||
initializeViewer() {
|
||||
Viewer.setDefaults({
|
||||
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -171,7 +171,6 @@ import { getMedicalReviewDialog, sendMedicalReviewDialog } from '@/api/trials'
|
||||
import FeedbackForm from '@/views/trials/trials-panel/reading/medical-feedback/components/FeedbackForm'
|
||||
import mimAvatar from '@/assets/MIM.png'
|
||||
import irAvatar from '@/assets/IR.png'
|
||||
import Viewer from 'v-viewer'
|
||||
export default {
|
||||
name: 'ChatForm',
|
||||
components: {
|
||||
@@ -207,7 +206,6 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initializeViewer()
|
||||
this.getMessageList()
|
||||
},
|
||||
methods: {
|
||||
@@ -261,11 +259,6 @@ export default {
|
||||
this.irFeedbackForm.title = this.$t('trials:medicalFeedback:title:feedback')
|
||||
|
||||
this.irFeedbackForm.visible = true
|
||||
},
|
||||
initializeViewer() {
|
||||
Viewer.setDefaults({
|
||||
toolbar: { zoomIn: true, zoomOut: true, rotateLeft: true, rotateRight: true, flipHorizontal: true, flipVertical: true }
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -197,7 +197,6 @@
|
||||
import { saveMedicalReviewInfo } from "@/api/trials";
|
||||
import ChatForm from "./ChatForm";
|
||||
import CloseQC from "./CloseQC";
|
||||
import Viewer from "v-viewer";
|
||||
export default {
|
||||
name: "AuditConclusions",
|
||||
components: {
|
||||
@@ -253,7 +252,6 @@ export default {
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.initializeViewer();
|
||||
this.initForm();
|
||||
},
|
||||
methods: {
|
||||
@@ -435,21 +433,9 @@ export default {
|
||||
var idx = this.fileList.findIndex((i) => i.url === file.url);
|
||||
if (idx === -1) return;
|
||||
this.fileList.splice(idx, 1);
|
||||
},
|
||||
initializeViewer() {
|
||||
Viewer.setDefaults({
|
||||
toolbar: {
|
||||
zoomIn: true,
|
||||
zoomOut: true,
|
||||
rotateLeft: true,
|
||||
rotateRight: true,
|
||||
flipHorizontal: true,
|
||||
flipVertical: true,
|
||||
},
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.conclusions {
|
||||
|
||||
@@ -1,17 +1,15 @@
|
||||
<template>
|
||||
<!-- <el-tabs v-model="activeName" v-loading="loading" style="min-height:500px">-->
|
||||
<!-- <el-tab-pane-->
|
||||
<!-- v-for="criterion in criterions"-->
|
||||
<!-- :key="criterion.ReadingQuestionCriterionTrialId"-->
|
||||
<!-- :label="criterion.ReadingQuestionCriterionTrialName"-->
|
||||
<!-- :name="criterion.ReadingQuestionCriterionTrialId"-->
|
||||
<!-- >-->
|
||||
<div v-loading="loading" style="min-height:500px">
|
||||
<h3 v-if="isReadingShowSubjectInfo" style="padding: 5px 0px;margin: 0;">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
<span style="margin-left:5px;">{{ taskBlindName }}</span>
|
||||
</h3>
|
||||
<ECRF
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:criterion-id="criterionId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@@ -43,6 +41,22 @@ export default {
|
||||
criterionId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
subjectCode: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
taskBlindName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
iseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
||||
@@ -77,13 +77,13 @@
|
||||
|
||||
<el-form-item v-if="readingTaskState < 2">
|
||||
<div style="text-align:center;">
|
||||
<el-button type="primary" @click="skipTask">
|
||||
<el-button type="primary" @click="skipTask" v-if="iseCRFShowInDicomReading">
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleSave">
|
||||
<el-button type="primary" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleSubmit">
|
||||
<el-button type="primary" @click="handleSubmit" v-if="iseCRFShowInDicomReading">
|
||||
{{ $t('common:button:submit') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -116,7 +116,7 @@ import const_ from '@/const/sign-code'
|
||||
import FormItem from './FormItem'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
// import { getToken } from '@/utils/auth'
|
||||
// import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
export default {
|
||||
name: 'ECRF',
|
||||
components: {
|
||||
@@ -139,6 +139,10 @@ export default {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
iseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -158,6 +162,9 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.getQuestions()
|
||||
DicomEvent.$on('refreshQuestionAnswer', _ => {
|
||||
this.getQuestions()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
async getQuestions() {
|
||||
@@ -243,6 +250,7 @@ export default {
|
||||
try {
|
||||
const res = await saveVisitTaskQuestions(params)
|
||||
if (res.IsSuccess) {
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.loading = false
|
||||
@@ -285,6 +293,7 @@ export default {
|
||||
const res = await submitVisitTaskQuestionsInDto(params)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.isEdit = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
|
||||
@@ -0,0 +1,934 @@
|
||||
<template>
|
||||
<div class="report-wrapper">
|
||||
<el-card v-loading="loading" shadow="never" style="display:flex;flex-direction: column;">
|
||||
<div slot="header" class="clearfix report-header">
|
||||
<h3 style="margin:0;padding:0;">{{ $t('trials:readingReport:title:eicrf') }}</h3>
|
||||
<div style="margin-left:auto">
|
||||
<!-- <el-switch
|
||||
v-model="isShowDetail"
|
||||
:active-text="$t('trials:readingReport:title:expandDetails')"
|
||||
:inactive-text="$t('trials:readingReport:title:collapseDetails')"
|
||||
style="margin-right:5px"
|
||||
@change="handleShowDetail"
|
||||
/> -->
|
||||
<el-button
|
||||
v-if="readingTaskState<2"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="skipTask"
|
||||
>
|
||||
<!-- 跳过 -->
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="getReportInfo">{{$t('trials:readingReport:button:refresh')}}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleSave(true)">{{$t('common:button:save')}}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleConfirm">{{$t('common:button:submit')}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: 1">
|
||||
<el-table
|
||||
ref="reportList"
|
||||
v-adaptive="{bottomOffset:0}"
|
||||
:data="taskQuestions"
|
||||
v-if="taskQuestions.length > 0"
|
||||
row-key="Id"
|
||||
border
|
||||
default-expand-all
|
||||
height="100"
|
||||
:tree-props="{children: 'Childrens', hasChildren: 'hasChildren'}"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label=""
|
||||
show-overflow-tooltip
|
||||
width="350px"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.QuestionName">{{ scope.row.BlindName ? scope.row.QuestionName : scope.row.QuestionName }}</span>
|
||||
<span
|
||||
v-else
|
||||
style="font-weight: bold;font-size: 16px;color: #f44336;"
|
||||
>
|
||||
{{ scope.row.GroupName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="task in visitTaskList"
|
||||
:key="task.VisitTaskId"
|
||||
prop="date"
|
||||
show-overflow-tooltip
|
||||
width="200px"
|
||||
>
|
||||
<template slot="header">
|
||||
<div v-if="task.IsCurrentTask">
|
||||
{{ task.BlindName }}
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
{{ task.BlindName }}
|
||||
<el-button type="text" size="small" @click="previewDicoms(task)">
|
||||
<span class="el-icon-view"></span>
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- <div v-if="task.LatestScanDate">-->
|
||||
<!-- {{ task.LatestScanDate.split(' ')[0] }}-->
|
||||
<!-- </div>-->
|
||||
<!-- {{ `(影像点击跳转)` }} -->
|
||||
<!-- {{ $t('trials:readingReport:button:jump') }}-->
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<template v-if="readingTaskState<2 && task.VisitTaskId === visitTaskId && (scope.row.Type==='input' || scope.row.Type==='number' || scope.row.Type==='select' || scope.row.Type==='textarea' || scope.row.Type==='radio')">
|
||||
<template>
|
||||
<!-- 输入框 -->
|
||||
<div>
|
||||
<template v-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)">
|
||||
</template>
|
||||
<el-input
|
||||
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
size="mini"
|
||||
/>
|
||||
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea')">
|
||||
{{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}}
|
||||
</span>
|
||||
<el-input
|
||||
v-else-if="(scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId]"
|
||||
size="mini"
|
||||
/>
|
||||
<span v-else-if="scope.row.Type==='input' || scope.row.Type==='textarea'">
|
||||
{{questionForm[scope.row.QuestionId]}}
|
||||
</span>
|
||||
<el-select
|
||||
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
size="mini"
|
||||
clearable
|
||||
>
|
||||
<template>
|
||||
<el-option
|
||||
v-for="val in scope.row.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='select'">
|
||||
{{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}}
|
||||
</span>
|
||||
<el-select
|
||||
v-else-if="(scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId]"
|
||||
size="mini"
|
||||
clearable
|
||||
>
|
||||
<template>
|
||||
<el-option
|
||||
v-for="val in scope.row.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<span v-else-if="scope.row.Type==='select' || scope.row.Type==='radio'">
|
||||
{{questionForm[scope.row.QuestionId]}}
|
||||
</span>
|
||||
<el-input
|
||||
v-else-if="scope.row.DataSource !== 1 && questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='number' && (scope.row.xfIndex || scope.row.xfIndex === 0) && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
:disabled="scope.row.DataSource === 1"
|
||||
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')))"
|
||||
@input="limitInput($event, questionForm[scope.row.QuestionId][scope.row.xfIndex], scope.row.TableQuestionId)"
|
||||
size="mini"
|
||||
@focus="() => {questionId = scope.row.QuestionId}"
|
||||
>
|
||||
<template slot="append" v-if="scope.row.Unit !== 0">{{scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit}}</template>
|
||||
<template slot="append" v-else-if="scope.row.ValueType === 2">%</template>
|
||||
</el-input>
|
||||
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='number' && (scope.row.xfIndex || scope.row.xfIndex === 0)">
|
||||
<template v-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]))? questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]:`${questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||
</template>
|
||||
<template v-else-if="scope.row.ValueType === 2">
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId])) ? questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]:`${questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]} %` }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId])) ? questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]:`${questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}` }}
|
||||
</template>
|
||||
</span>
|
||||
<el-input
|
||||
v-else-if="scope.row.DataSource !== 1 && scope.row.Type==='number' && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId]"
|
||||
:disabled="scope.row.DataSource === 1"
|
||||
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')))"
|
||||
@input="limitInput($event, questionForm, scope.row.QuestionId)"
|
||||
size="mini"
|
||||
@focus="() => {questionId = scope.row.QuestionId}"
|
||||
>
|
||||
<template slot="append" v-if="scope.row.Unit !== 0">{{scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit}}</template>
|
||||
<template slot="append" v-else-if="scope.row.ValueType === 2">%</template>
|
||||
</el-input>
|
||||
<span v-else-if="scope.row.Type==='number'">
|
||||
<template v-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId]))? questionForm[scope.row.QuestionId]:`${questionForm[scope.row.QuestionId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||
</template>
|
||||
<template v-else-if="scope.row.ValueType === 2">
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId]:`${questionForm[scope.row.QuestionId]} %` }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId] : questionForm[scope.row.QuestionId]}}
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.Type === 'upload'">
|
||||
<UploadFile
|
||||
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
|
||||
:visitTaskId="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}"
|
||||
></UploadFile>
|
||||
<UploadFile
|
||||
v-else-if="scope.row.Type==='upload'"
|
||||
:visitTaskId="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="questionForm[scope.row.QuestionId]"
|
||||
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
|
||||
></UploadFile>
|
||||
</template>
|
||||
<template v-else-if="scope.row.Type === 'upload'">
|
||||
<UploadFile
|
||||
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
|
||||
:visitTaskId="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="scope.row.Answers[task.VisitTaskId]"
|
||||
></UploadFile>
|
||||
<UploadFile
|
||||
v-else-if="scope.row.Type==='upload'"
|
||||
:visitTaskId="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="scope.row.Answers[task.VisitTaskId]"
|
||||
></UploadFile>
|
||||
</template>
|
||||
<template v-else-if="scope.row.QuestionType=== 22">
|
||||
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }}
|
||||
</template>
|
||||
<template v-else-if="scope.row.DictionaryCode">
|
||||
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
||||
</template>
|
||||
<template v-else-if="CriterionType === 10">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]}` }}
|
||||
</template>
|
||||
<template v-else-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)">
|
||||
</template>
|
||||
<template v-else-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||
</template>
|
||||
<template v-else-if="scope.row.ValueType === 2">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId])) ? scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]} %` }}
|
||||
</template>
|
||||
<template v-else-if="scope.row.Answers && scope.row.Answers.hasOwnProperty(task.VisitTaskId)">
|
||||
{{ scope.row.Answers[task.VisitTaskId] }}
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
<!-- 签名框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div slot="title">
|
||||
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
||||
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
|
||||
</div>
|
||||
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
import UploadFile from './UploadFile'
|
||||
import const_ from '@/const/sign-code'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import store from '@/store'
|
||||
export default {
|
||||
name: 'Report',
|
||||
components: { SignForm, UploadFile },
|
||||
props: {
|
||||
trialId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
subjectId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
readingTool: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
criterionType: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isReadingTaskViewInOrder: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
visitTaskList: [],
|
||||
taskQuestions: [],
|
||||
loading: false,
|
||||
answers: [],
|
||||
readingTaskState: 2,
|
||||
tumorEvaluate: null,
|
||||
currentEvaluateResult: null,
|
||||
isExistDisease: null,
|
||||
currentExistDisease: null,
|
||||
currentTaskReason: '',
|
||||
answerArr: [],
|
||||
questions: [],
|
||||
isShowDetail: false,
|
||||
CriterionType: 0,
|
||||
CalculationList: [],
|
||||
TrialReadingCriterionId: null,
|
||||
tableAnswers: {},
|
||||
questionForm: {},
|
||||
questionId: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v, oldv) {
|
||||
try {
|
||||
if (!v[this.questionId] || !oldv[this.questionId]) return
|
||||
} catch (e) {
|
||||
}
|
||||
this.formItemNumberChange(this.questionId, false)
|
||||
}
|
||||
},
|
||||
taskQuestions() {
|
||||
this.$nextTick(() => {
|
||||
this.setScrollTop()
|
||||
})
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
this.digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
|
||||
this.TrialReadingCriterionId = this.$route.query.TrialReadingCriterionId
|
||||
window.addEventListener('resize', () => {
|
||||
this.handleResize()
|
||||
this.setScrollTop()
|
||||
})
|
||||
DicomEvent.$on('getReportInfo', isRefresh => {
|
||||
if (!isRefresh) return
|
||||
this.getReportInfo()
|
||||
})
|
||||
await this.getQuestionCalculateRelation()
|
||||
this.getReportInfo()
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('getReportInfo')
|
||||
},
|
||||
methods: {
|
||||
limitInput(value, a, b) {
|
||||
if (value.indexOf('.') > -1) {
|
||||
if (value.split('.')[1].length >= this.digitPlaces) {
|
||||
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
|
||||
}
|
||||
} else {
|
||||
}
|
||||
},
|
||||
setImageUrl(qid, index, tqid, url, RowId) {
|
||||
if (index || index === 0) {
|
||||
// 表格问题
|
||||
this.$set(this.questionForm[qid][index], tqid, url)
|
||||
this.$set(this.questionForm[qid][index], tqid + '_RowId', RowId)
|
||||
// this.questionForm[qid][index][tqid] = url
|
||||
} else {
|
||||
// 非表格问题
|
||||
this.questionForm[qid] = url
|
||||
}
|
||||
},
|
||||
getTagterAnswers(list, questionId) {
|
||||
let Answers
|
||||
list.forEach(v => {
|
||||
if (v.QuestionId === questionId) {
|
||||
return Object.assign({}, v.Answers)
|
||||
} else if (v.Childrens.length > 0){
|
||||
return this.getTagterAnswers(v.Childrens, questionId)
|
||||
}
|
||||
})
|
||||
},
|
||||
formItemNumberChange(questionId, isTable) {
|
||||
if (isTable) {
|
||||
this.CalculationList.forEach((v, i) => {
|
||||
var find = v.CalculateQuestionList.filter(o => {
|
||||
return o.QuestionId === questionId
|
||||
})
|
||||
// find的自动计算值number
|
||||
if (find) {
|
||||
var num = this.logic(v)
|
||||
if (num !== false) {
|
||||
this.$set(this.questionForm, v.QuestionId, num)
|
||||
// this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.CalculationList.forEach(v => {
|
||||
var find = v.CalculateQuestionList.filter(o => {
|
||||
return o.TableQuestionId === questionId
|
||||
})
|
||||
// find的自动计算值number
|
||||
if (find) {
|
||||
var num = this.logic(v)
|
||||
if (num !== false) {
|
||||
this.$set(this.questionForm, v.QuestionId, num)
|
||||
// this.$emit('setFormItemData', { key: v.QuestionId, val: num })
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
// this.$emit('formItemNumberChange')
|
||||
},
|
||||
getTableAnswers(QuestionId, list) {
|
||||
var arr = []
|
||||
window.xfList = list
|
||||
list.forEach((v, i) => {
|
||||
var obj = {}
|
||||
v.Childrens.forEach((o) => {
|
||||
this.$set(o, 'xfIndex', i)
|
||||
obj[o.TableQuestionId + '_RowId'] = o.RowId
|
||||
obj[o.TableQuestionId] = o.Answers[this.visitTaskId]
|
||||
})
|
||||
arr.push(obj)
|
||||
})
|
||||
return arr
|
||||
},
|
||||
InitVisitTaskQuestionForm() {
|
||||
this.taskQuestions.map((v, i) => {
|
||||
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return
|
||||
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') {
|
||||
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId])
|
||||
}
|
||||
if (v.Type === 'table') {
|
||||
var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i)
|
||||
this.$set(this.questionForm, v.QuestionId, tableAnswers)
|
||||
// this.$set(v, 'xfIndex', i)
|
||||
}
|
||||
if (v.Type === 'number') {
|
||||
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : v.Answers[this.visitTaskId])
|
||||
}
|
||||
if (v.Childrens.length > 0) {
|
||||
this.setChild(v.Childrens)
|
||||
}
|
||||
})
|
||||
this.formItemNumberChange(this.questionId, false)
|
||||
},
|
||||
setChild(obj) {
|
||||
obj.forEach((i, index) => {
|
||||
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table') {
|
||||
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId])
|
||||
}
|
||||
if (i.Type === 'table') {
|
||||
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
|
||||
this.$set(this.questionForm, i.QuestionId, tableAnswers)
|
||||
}
|
||||
if (i.Type === 'number') {
|
||||
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : i.Answers[this.visitTaskId])
|
||||
}
|
||||
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table') {
|
||||
this.setChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
getQuestionCalculateRelation() {
|
||||
return new Promise(resolve => {
|
||||
getQuestionCalculateRelation({
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId
|
||||
}).then(res => {
|
||||
this.CalculationList = res.Result
|
||||
resolve()
|
||||
})
|
||||
})
|
||||
},
|
||||
logic(rules, num = 0) {
|
||||
try {
|
||||
if (rules.CalculateQuestionList.length === 0) {
|
||||
return false
|
||||
}
|
||||
rules.CalculateQuestionList.forEach((o, i) => {
|
||||
if (i === 0) {
|
||||
if (rules.CustomCalculateMark > 4) {
|
||||
switch (rules.CustomCalculateMark) {
|
||||
case 5:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
num = parseFloat(q[o.TableQuestionId])
|
||||
} else {
|
||||
num *= parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
break;
|
||||
case 6:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
num = isNaN(parseFloat(q[o.TableQuestionId])) ? null : parseFloat(q[o.TableQuestionId])
|
||||
} else {
|
||||
num += isNaN(parseFloat(q[o.TableQuestionId])) ? null : parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
break;
|
||||
case 7:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
num = parseFloat(q[o.TableQuestionId])
|
||||
} else {
|
||||
num += parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
|
||||
break;
|
||||
case 8:
|
||||
var arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.max(...arr)
|
||||
break;
|
||||
case 9:
|
||||
var arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.min(...arr)
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
num = parseFloat(this.questionForm[o.TableQuestionId])
|
||||
}
|
||||
} else {
|
||||
switch (rules.CustomCalculateMark) {
|
||||
case 1:
|
||||
num += parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
case 2:
|
||||
num -= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
case 3:
|
||||
num *= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
case 4:
|
||||
num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
// num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
}
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
|
||||
if (rules.ValueType === 2) {
|
||||
num = num * 100
|
||||
}
|
||||
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(digitPlaces) : '∞'
|
||||
},
|
||||
getReportInfo() {
|
||||
this.loading = true
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.$router.currentRoute.query.trialId
|
||||
}
|
||||
this.taskQuestions = []
|
||||
getReadingReportEvaluation(params).then(res => {
|
||||
this.readingTaskState = res.Result.ReadingTaskState
|
||||
this.tumorEvaluate = res.Result.CalculateResult.TumorEvaluate ? parseInt(res.Result.CalculateResult.TumorEvaluate) : null
|
||||
this.isExistDisease = res.Result.CalculateResult.IsExistDisease ? parseInt(res.Result.CalculateResult.IsExistDisease) : null
|
||||
this.answerArr = []
|
||||
this.questions = res.Result.TaskQuestions.concat()
|
||||
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
|
||||
taskQuestions.forEach(item => {
|
||||
this.$set(this.taskQuestions, this.taskQuestions.length, item)
|
||||
})
|
||||
this.visitTaskList = res.Result.VisitTaskList
|
||||
this.InitVisitTaskQuestionForm()
|
||||
this.handleResize()
|
||||
this.setScrollTop()
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
setScrollTop(a) {
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
if(this.$refs.reportList){
|
||||
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
|
||||
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
|
||||
}
|
||||
})
|
||||
},50)
|
||||
},
|
||||
getQuestions(questions, isNTFilterLength, lesionType, isLymphNodes) {
|
||||
const arr = []
|
||||
if (questions.length !== 0) {
|
||||
questions.forEach((item) => {
|
||||
// 过滤病灶标识 病灶名称 部位 器官 位置 是否淋巴结
|
||||
// 非靶病灶和新病灶 过滤长径和短径信息
|
||||
// 非淋巴结靶病灶 过滤短径
|
||||
|
||||
lesionType = item.LesionType
|
||||
var filterArr = []
|
||||
if ((item.LesionType === 1 || item.LesionType === 2) && isNTFilterLength) {
|
||||
filterArr = [0, 1, 3, 4, 5, 6, 2, 8, 10]
|
||||
} else {
|
||||
filterArr = [3, 4, 5, 6, 2, 8, 10]
|
||||
}
|
||||
if (lesionType === 0 && isLymphNodes === 0 && !this.isShowDetail && this.CriterionType === 1) {
|
||||
filterArr.push(1)
|
||||
}
|
||||
if (!(filterArr.includes(item.QuestionMark))) {
|
||||
const obj = item
|
||||
this.$set(obj, 'Answers', {})
|
||||
// obj.Answers = {}
|
||||
if (item.RowIndex > 0) {
|
||||
var idx = item.Childrens.findIndex(i => i.QuestionMark === 8)
|
||||
var idxLoc = item.Childrens.findIndex(i => i.QuestionMark === 10)
|
||||
|
||||
if (idx > -1) {
|
||||
if (item.Childrens[idx].Answer.length > 0) {
|
||||
var k = item.Childrens[idx].Answer.findIndex(v => v.Answer !== '')
|
||||
var part = ''
|
||||
if (obj.IsCanEditPosition) {
|
||||
part = `${item.Childrens[idx].Answer[k].Answer}--${item.Childrens[idxLoc].Answer[k].Answer}`
|
||||
} else {
|
||||
part = `${item.Childrens[idx].Answer[k].Answer}`
|
||||
}
|
||||
|
||||
if (item.SplitOrMergeLesionName && k > -1) {
|
||||
obj.QuestionName = `${obj.QuestionName} --${part} (Split from ${item.SplitOrMergeLesionName})`
|
||||
// obj.QuestionName = `${obj.QuestionName} `
|
||||
} else if (!item.SplitOrMergeLesionName && k > -1) {
|
||||
obj.QuestionName = `${obj.QuestionName} --${part}`
|
||||
// obj.QuestionName = `${obj.QuestionName} `
|
||||
} else {
|
||||
obj.QuestionName = `${obj.QuestionName} `
|
||||
}
|
||||
|
||||
if (this.CriterionType === 1) {
|
||||
var idxLymphNode = item.Childrens.findIndex(i => i.QuestionMark === 2)
|
||||
if (idxLymphNode > -1) {
|
||||
isLymphNodes = item.Childrens[idxLymphNode].Answer[k].Answer ? parseInt(item.Childrens[idxLymphNode].Answer[k].Answer) : null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var digitPlaces = parseInt(localStorage.getItem('digitPlaces')) || 0
|
||||
item.Answer.forEach(i => {
|
||||
if (item.DictionaryCode) {
|
||||
this.$set(obj.Answers, i.VisitTaskId, i.Answer ? parseInt(i.Answer) : null)
|
||||
// obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
||||
} else {
|
||||
if (item.Type === 'number') {
|
||||
this.$set(obj.Answers, i.VisitTaskId, isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(digitPlaces))
|
||||
} else {
|
||||
this.$set(obj.Answers, i.VisitTaskId, i.Answer)
|
||||
}
|
||||
// obj.Answers[i.VisitTaskId] = i.Answer
|
||||
}
|
||||
})
|
||||
if (item.Childrens.length >= 1) {
|
||||
obj.Childrens = this.getQuestions(item.Childrens, isNTFilterLength, lesionType, isLymphNodes)
|
||||
}
|
||||
arr.push(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr
|
||||
},
|
||||
handleShowDetail(val) {
|
||||
this.getReportInfo()
|
||||
// this.taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null)
|
||||
},
|
||||
handleExistDiseaseChange(val) {
|
||||
// this.currentExistDisease = parseInt(val)
|
||||
|
||||
if (val === this.isExistDisease && this.tumorEvaluate === this.currentEvaluateResult) {
|
||||
this.currentTaskReason = ''
|
||||
this.evaluateReasonChange('')
|
||||
}
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 15)
|
||||
if (idx > -1) {
|
||||
this.answerArr[idx].answer = val
|
||||
}
|
||||
},
|
||||
handleEvaluateResultChange(val) {
|
||||
// this.currentEvaluateResult = parseInt(val)
|
||||
if (val === this.tumorEvaluate && this.isExistDisease === this.currentExistDisease) {
|
||||
this.currentTaskReason = ''
|
||||
this.evaluateReasonChange('')
|
||||
}
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 13)
|
||||
if (idx > -1) {
|
||||
this.answerArr[idx].answer = val
|
||||
}
|
||||
},
|
||||
|
||||
evaluateReasonChange(val) {
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 14)
|
||||
if (idx > -1) {
|
||||
this.answerArr[idx].answer = val
|
||||
}
|
||||
},
|
||||
async handleConfirm() {
|
||||
await this.handleSave(false)
|
||||
await this.verifyVisitTaskQuestions()
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
},
|
||||
verifyVisitTaskQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId }).then(res => {
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
handleResize() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportList.doLayout()
|
||||
})
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
var params = {
|
||||
data: {
|
||||
visitTaskId: this.visitTaskId
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
submitDicomVisitTask(params).then(res => {
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
if (this.$refs['signForm']) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
|
||||
this.signVisible = false
|
||||
// window.location.reload()
|
||||
// window.opener.postMessage('refreshTaskList', window.location)
|
||||
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
|
||||
DicomEvent.$emit('setReadingState', 2)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
// var token = getToken()
|
||||
// var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
// var subjectId = this.$router.currentRoute.query.subjectId
|
||||
// var trialId = this.$router.currentRoute.query.trialId
|
||||
|
||||
// this.$router.push({
|
||||
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
|
||||
// })
|
||||
// DicomEvent.$emit('getNextTask')
|
||||
window.location.reload()
|
||||
})
|
||||
.catch(action => {
|
||||
|
||||
})
|
||||
}
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
})
|
||||
},
|
||||
previewDicoms(task) {
|
||||
var token = getToken()
|
||||
// var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
var subjectCode = localStorage.getItem('subjectCode')
|
||||
var subjectId = this.subjectId
|
||||
var trialId = this.trialId
|
||||
var isReadingTaskViewInOrder = this.isReadingTaskViewInOrder
|
||||
var criterionType = this.criterionType
|
||||
var readingTool = this.readingTool
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
const routeData = this.$router.resolve({ path })
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
handleSave(isPrompt) {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var answers = []
|
||||
var tableQuestionAnswer = []
|
||||
for (const k in this.questionForm) {
|
||||
if (this.questionForm[k] instanceof Array) {
|
||||
this.questionForm[k].forEach((v, i) => {
|
||||
Object.keys(v).forEach(o => {
|
||||
if (o.indexOf('_RowId') === -1) {
|
||||
tableQuestionAnswer.push({
|
||||
questionId: k,
|
||||
answer: v[o],
|
||||
tableQuestionId: o,
|
||||
rowId: v[o+'_RowId']
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
// tableQuestionAnswer.push({})
|
||||
} else {
|
||||
answers.push({ questionId: k, answer: this.questionForm[k].toString() })
|
||||
}
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
questionAnswer: answers,
|
||||
tableQuestionAnswer: tableQuestionAnswer
|
||||
}
|
||||
changeCalculationAnswer(params).then(res => {
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
DicomEvent.$emit('refreshQuestionAnswer')
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
async skipTask() {
|
||||
try {
|
||||
// 是否确认跳过?
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:readingReport:message:skipConfirm'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
this.loading = true
|
||||
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
window.location.reload()
|
||||
}
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.report-wrapper{
|
||||
|
||||
height: 100%;
|
||||
// background-color: #fff;
|
||||
// background-color: #000;
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
// background: #d0d0d0;
|
||||
}
|
||||
.report-header{
|
||||
display: flex;
|
||||
}
|
||||
.el-card{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
border:none;
|
||||
}
|
||||
/deep/ .el-table--border th.gutter:last-of-type{
|
||||
border: none;
|
||||
}
|
||||
/deep/ .el-card__header{
|
||||
border: none;
|
||||
padding: 10px;
|
||||
}
|
||||
/deep/ .el-upload-list--picture-card .el-upload-list__item{
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
/deep/ .el-upload--picture-card{
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 40px;
|
||||
}
|
||||
}
|
||||
/deep/ .el-switch__label.is-active{
|
||||
color: #428bca;
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div>
|
||||
<el-upload
|
||||
:action="accept"
|
||||
:limit="question.ImageCount"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:http-request="uploadScreenshot"
|
||||
list-type="picture-card"
|
||||
:on-remove="handleRemove"
|
||||
:file-list="fileList"
|
||||
:class="{disabled:readingTaskState >= 2 || (fileList.length >= question.ImageCount) || (task.VisitTaskId !== visitTaskId) || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))}"
|
||||
:disabled="readingTaskState >= 2 || task.VisitTaskId !== visitTaskId || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))"
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<viewer
|
||||
:ref="file.url"
|
||||
:images="[imageUrl]"
|
||||
style="
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
"
|
||||
>
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
crossOrigin="anonymous"
|
||||
alt=""
|
||||
style="max-width: 100%; max-height: 100%"
|
||||
/>
|
||||
<span class="el-upload-list__item-actions">
|
||||
<span
|
||||
class="el-upload-list__item-preview"
|
||||
@click="handlePictureCardPreview(file)"
|
||||
>
|
||||
<i class="el-icon-zoom-in" />
|
||||
</span>
|
||||
|
||||
<span
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-upload-list__item-delete"
|
||||
@click="handleRemove(file)"
|
||||
>
|
||||
<i class="el-icon-delete" />
|
||||
</span>
|
||||
</span>
|
||||
</viewer>
|
||||
</div>
|
||||
</el-upload>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: "UploadFile",
|
||||
props: {
|
||||
task: {
|
||||
Type: Object,
|
||||
required: true
|
||||
},
|
||||
question: {
|
||||
Type: Object,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
initUrl: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
imgVisible: false,
|
||||
imageUrl: null,
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
fileList: [],
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.urls = this.initUrl === '' ? [] : this.initUrl.split('|')
|
||||
console.log(this.visitTaskId, this.urls)
|
||||
this.fileList = []
|
||||
this.urls.map(url => {
|
||||
this.fileList.push({ name: '', url: `${url}` })
|
||||
})
|
||||
console.log(this.fileList)
|
||||
},
|
||||
methods: {
|
||||
checkFileSuffix(fileName) {
|
||||
var index = fileName.lastIndexOf('.')
|
||||
var suffix = fileName.substring(index + 1, fileName.length)
|
||||
if (this.accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
},
|
||||
async uploadScreenshot(param) {
|
||||
if (!this.visitTaskId) return
|
||||
const loading = this.$loading({
|
||||
target: document.querySelector('.ecrf-wrapper'),
|
||||
fullscreen: false,
|
||||
lock: true,
|
||||
text: 'Loading',
|
||||
spinner: 'el-icon-loading'
|
||||
})
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
var file = await this.fileToBlob(param.file)
|
||||
const res = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${param.file.name}`, file)
|
||||
console.log(res)
|
||||
this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url)})
|
||||
this.urls.push(this.$getObjectName(res.url))
|
||||
this.$emit('setImageUrl', this.urls.length > 0 ? this.urls.join('|') : '')
|
||||
loading.close()
|
||||
},
|
||||
handleBeforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
// this.fileList = []
|
||||
return true
|
||||
} else {
|
||||
this.$alert(`必须是 ${this.accept} 格式`)
|
||||
return false
|
||||
}
|
||||
},
|
||||
// 预览图片
|
||||
handlePictureCardPreview(file) {
|
||||
var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
|
||||
suffix = suffix ? suffix.toLowerCase() : ''
|
||||
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
|
||||
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
|
||||
}else{
|
||||
this.imageUrl = this.OSSclientConfig.basePath + file.url
|
||||
// this.imgVisible = true
|
||||
this.$refs[file.url].$viewer.show()
|
||||
}
|
||||
},
|
||||
// 删除图片
|
||||
handleRemove(file, fileList) {
|
||||
this.imageUrl = ''
|
||||
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
|
||||
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
|
||||
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.disabled{
|
||||
/deep/ .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,9 +1,9 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="img-container">
|
||||
<el-card class="box-card left">
|
||||
<div v-if="otherInfo && otherInfo.IsReadingShowSubjectInfo" class="title">
|
||||
<span>{{ $t('trials:auditRecord:table:subject') }}:{{ otherInfo.SubjectCode }} </span>
|
||||
<span>({{ otherInfo.TaskBlindName }})</span>
|
||||
<div v-if="isReadingShowSubjectInfo" class="title">
|
||||
<h4>{{ subjectCode }} </h4>
|
||||
<h4>{{ taskBlindName }}</h4>
|
||||
</div>
|
||||
<el-tabs v-model="activeName" @tab-click="handleClick">
|
||||
<el-tab-pane :label="$t('trials:clinicaldara:title:currentTask')" name="first" class="left-content">
|
||||
@@ -93,6 +93,10 @@
|
||||
:subject-id="subjectId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:criterion-id="otherInfo.TrialCriterionId"
|
||||
:subjectCode="subjectCode"
|
||||
:taskBlindName="taskBlindName"
|
||||
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
@@ -127,9 +131,33 @@ export default {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
taskBlindName: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
readingCategory: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
readingTool: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
criterionType: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
isReadingTaskViewInOrder: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
iseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -156,7 +184,8 @@ export default {
|
||||
currentTaskId: '',
|
||||
otherInfo: null,
|
||||
isReadingShowPreviousResults: false,
|
||||
bp: []
|
||||
bp: [],
|
||||
openWindow: null
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -170,6 +199,11 @@ export default {
|
||||
|
||||
this.getNoneDicomList(this.isReadingShowPreviousResults)
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 获取非Dicom检查信息
|
||||
getNoneDicomList() {
|
||||
@@ -250,18 +284,21 @@ export default {
|
||||
})
|
||||
},
|
||||
handleImageRead(task) {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close()
|
||||
}
|
||||
this.currentTaskId = task.VisitTaskId
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var criterionType = this.criterionType
|
||||
var readingTool = this.readingTool
|
||||
var isReadingTaskViewInOrder = this.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var token = getToken()
|
||||
const path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
const path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
// const routeData = this.$router.resolve({
|
||||
// path: `/readingPage?subjectId=${this.subjectId}&trialId=${this.trialId}&visitTaskId=${task.VisitTaskId}&TokenKey=${token}`
|
||||
// })
|
||||
const routeData = this.$router.resolve({ path })
|
||||
window.open(routeData.href, '_blank')
|
||||
this.openWindow = window.open(routeData.href, '_blank')
|
||||
},
|
||||
previewCD() {
|
||||
var token = getToken()
|
||||
@@ -295,7 +332,7 @@ export default {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 10px;
|
||||
padding-bottom: 10px;
|
||||
display: flex;
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
@@ -326,13 +363,19 @@ export default {
|
||||
flex-direction: column;
|
||||
}
|
||||
.title{
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
// height: 40px;
|
||||
// line-height: 40px;
|
||||
border: 1ppx solid;
|
||||
border: 1px solid #ebe7e7;
|
||||
padding-left: 10px;
|
||||
// padding-left: 10px;
|
||||
background-color: #4e4e4e;
|
||||
color: #ffffff;
|
||||
h4{
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
background-color: #4c4c4c;
|
||||
}
|
||||
}
|
||||
.left-content{
|
||||
flex: 1;
|
||||
|
||||
@@ -1,15 +1,40 @@
|
||||
<template>
|
||||
<div ref="container" v-loading="loading" class="none-dicom-reading-container">
|
||||
<!-- 访视阅片 -->
|
||||
<VisitReview
|
||||
v-if="isShow && readingCategory && readingCategory=== 1"
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:subject-code="subjectCode"
|
||||
:visit-task-id="visitTaskId"
|
||||
:reading-category="readingCategory"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
/>
|
||||
<div v-if="isShow && readingCategory && readingCategory=== 1" class="reading-wrapper">
|
||||
<el-tabs v-model="activeName" :before-leave="beforeLeave">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
<VisitReview
|
||||
:trial-id="trialId"
|
||||
:subject-id="subjectId"
|
||||
:subject-code="subjectCode"
|
||||
:visit-task-id="visitTaskId"
|
||||
:task-blind-name="taskBlindName"
|
||||
:reading-category="readingCategory"
|
||||
:readingTool="readingTool"
|
||||
:criterionType="criterionType"
|
||||
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:report')" name="report" v-if="!iseCRFShowInDicomReading">
|
||||
<Report
|
||||
v-if="tabs.includes('report')"
|
||||
ref="reportPage"
|
||||
:trialId="trialId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:subject-id="subjectId"
|
||||
:readingTool="readingTool"
|
||||
:criterionType="criterionType"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
||||
<!-- 全局阅片 -->
|
||||
<GlobalReview
|
||||
v-else-if="isShow && readingCategory && readingCategory === 2"
|
||||
@@ -83,6 +108,7 @@ import { getNextTask, readClinicalData } from '@/api/trials'
|
||||
import store from '@/store'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
import Report from './components/Report'
|
||||
import VisitReview from './components/VisitReview'
|
||||
import GlobalReview from '@/views/trials/trials-panel/reading/global-review'
|
||||
import AdReview from '@/views/trials/trials-panel/reading/ad-review'
|
||||
@@ -93,6 +119,7 @@ export default {
|
||||
name: 'NoneDicomReading',
|
||||
components: {
|
||||
VisitReview,
|
||||
Report,
|
||||
AdReview,
|
||||
GlobalReview,
|
||||
OncologyReview,
|
||||
@@ -113,18 +140,21 @@ export default {
|
||||
isExistsClinicalData: false,
|
||||
isNeedReadClinicalData: false,
|
||||
isReadClinicalData: false,
|
||||
iseCRFShowInDicomReading: false,
|
||||
criterionType: null,
|
||||
readingTool: null,
|
||||
isNewSubject: null,
|
||||
dialogVisible: false,
|
||||
dialogH: 0,
|
||||
isShow: false
|
||||
isShow: false,
|
||||
activeName:'',
|
||||
tabs: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
DicomEvent.$on('getNextTask', () => {
|
||||
this.getTaskInfo()
|
||||
})
|
||||
})
|
||||
this.trialId = this.$router.currentRoute.query.trialId
|
||||
this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
this.subjectId = this.$router.currentRoute.query.subjectId
|
||||
@@ -169,6 +199,10 @@ export default {
|
||||
// var token = getToken()
|
||||
// window.location.href = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${res.Result.SubjectCode}&subjectId=${res.Result.SubjectId}&isReadingShowPreviousResults=${this.isReadingShowPreviousResults}&isReadingShowSubjectInfo=${this.isReadingShowSubjectInfo}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&isNewSubject=1&isReadingTaskViewInOrder=${res.Result.IsReadingTaskViewInOrder}&TokenKey=${token}`
|
||||
// }
|
||||
if (res.Result.ReadingCategory === 1) {
|
||||
this.activeName = 'read'
|
||||
this.tabs = [this.activeName]
|
||||
}
|
||||
this.subjectId = res.Result.SubjectId
|
||||
this.visitTaskId = res.Result.VisitTaskId
|
||||
this.subjectCode = res.Result.SubjectCode
|
||||
@@ -176,7 +210,8 @@ export default {
|
||||
this.isExistsClinicalData = res.Result.IsExistsClinicalData
|
||||
this.isReadClinicalData = res.Result.IsReadClinicalData
|
||||
this.isNeedReadClinicalData = res.Result.IsNeedReadClinicalData
|
||||
|
||||
this.iseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
|
||||
this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
|
||||
this.isReadingShowSubjectInfo = res.Result.IsReadingShowSubjectInfo
|
||||
this.isReadingShowPreviousResults = res.Result.IsReadingShowPreviousResults
|
||||
this.digitPlaces = res.Result.DigitPlaces
|
||||
@@ -201,7 +236,21 @@ export default {
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeLeave(activeName, oldActiveName) {
|
||||
if (!this.tabs.includes(activeName)) {
|
||||
this.tabs.push(activeName)
|
||||
}
|
||||
if (oldActiveName === 'read') {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.reportPage) {
|
||||
// DicomEvent.$emit('getReportInfo', true)
|
||||
this.$refs.reportPage.setScrollTop(1)
|
||||
}
|
||||
})
|
||||
}
|
||||
return Promise.resolve(true)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@@ -221,7 +270,38 @@ export default {
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
.reading-wrapper{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
padding: 0 10px;
|
||||
box-sizing: border-box;
|
||||
/deep/.el-tabs{
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.el-tabs__item{
|
||||
// color: #fff;
|
||||
}
|
||||
.el-tabs__header{
|
||||
height: 50px;
|
||||
margin:0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.el-tabs__content{
|
||||
flex: 1;
|
||||
margin:0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.el-tabs__item{
|
||||
// color: #fff;
|
||||
}
|
||||
.el-tab-pane{
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
/deep/ .dialog-container{
|
||||
margin-top: 50px !important;
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<!-- '表单问题' -->
|
||||
<el-form-item :label="$t('trials:readingUnit:readingCriterion:title:formQs')">
|
||||
<QuestionsList
|
||||
:ref="`questionList${trialReadingCriterionId}`"
|
||||
v-if="form.FormType===1"
|
||||
:trial-reading-criterion-id="trialReadingCriterionId"
|
||||
:list="readingInfo.TrialQuestionList"
|
||||
@@ -170,6 +171,9 @@ export default {
|
||||
})
|
||||
})
|
||||
},
|
||||
getQuestionLength() {
|
||||
return this.$refs['questionList' + this.trialReadingCriterionId].tblList.length
|
||||
},
|
||||
reloadArbitrationRules() {
|
||||
this.$emit('reloadArbitrationRules')
|
||||
},
|
||||
|
||||
@@ -131,6 +131,7 @@
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:IsAdditionalAssessment')"
|
||||
prop="IsAdditionalAssessment"
|
||||
v-if="CriterionType === 1"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsAdditionalAssessment"
|
||||
|
||||
@@ -370,11 +370,11 @@ export default {
|
||||
isCheck: readingRules,
|
||||
msg: this.$t("trials:readingUnit:readingRules"), // '阅片规则'
|
||||
});
|
||||
// var readingCriterions = await this.$refs['readingCriterions' + this.TrialReadingCriterionId][0].handleSave(false)
|
||||
// isCheckList.push({
|
||||
// isCheck: readingCriterions,
|
||||
// msg: '阅片标准'
|
||||
// })
|
||||
var qsLength = this.$refs['readingCriterions' + this.TrialReadingCriterionId][0].getQuestionLength()
|
||||
isCheckList.push({
|
||||
isCheck: qsLength > 0,
|
||||
msg: this.$t('trials:readingUnit:readingCriterion')
|
||||
})
|
||||
if (
|
||||
this.$refs["globalReading" + this.TrialReadingCriterionId] &&
|
||||
this.$refs["globalReading" + this.TrialReadingCriterionId]
|
||||
@@ -497,12 +497,16 @@ export default {
|
||||
});
|
||||
},
|
||||
reloadArbitrationRules() {
|
||||
this.$refs[
|
||||
if (this.$refs[
|
||||
"arbitrationRules" + this.TrialReadingCriterionId
|
||||
][0].getList();
|
||||
this.$refs[
|
||||
"arbitrationRules" + this.TrialReadingCriterionId
|
||||
][0].getTrialJudgyInfo();
|
||||
]) {
|
||||
this.$refs[
|
||||
"arbitrationRules" + this.TrialReadingCriterionId
|
||||
][0].getList();
|
||||
this.$refs[
|
||||
"arbitrationRules" + this.TrialReadingCriterionId
|
||||
][0].getTrialJudgyInfo();
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -1004,7 +1004,7 @@ export default {
|
||||
}
|
||||
}
|
||||
item.key = o ? ((o[v.Code] && o[v.Code] !== null && o[v.Code] !== '' || o[v.Code] !== 0) ? o[v.Code] : '--') : '--'
|
||||
item.Enum = v.ValueCN
|
||||
item.Enum = this.$i18n.locale === 'zh' ? v.ValueCN : v.Value
|
||||
item.DataType = v.DataType
|
||||
item.IsTableFiled = v.IsTableFiled
|
||||
this[auditData].push(item)
|
||||
@@ -1019,21 +1019,21 @@ export default {
|
||||
if (row.OptType === 'Add' || row.OptType === 'Init') {
|
||||
item = {
|
||||
key: v.Code,
|
||||
Enum: v.ValueCN,
|
||||
Enum: this.$i18n.locale === 'zh' ? v.ValueCN : v.Value,
|
||||
newValue: obj[v.Code] ? obj[v.Code] : '--',
|
||||
oldValue: ''
|
||||
}
|
||||
} else if (row.OptType === 'Delete') {
|
||||
item = {
|
||||
key: v.Code,
|
||||
Enum: v.ValueCN,
|
||||
Enum: this.$i18n.locale === 'zh' ? v.ValueCN : v.Value,
|
||||
oldValue: obj[v.Code] ? obj[v.Code] : '--',
|
||||
newValue: '--'
|
||||
}
|
||||
} else {
|
||||
item = {
|
||||
key: v.Code,
|
||||
Enum: v.ValueCN,
|
||||
Enum: this.$i18n.locale === 'zh' ? v.ValueCN : v.Value,
|
||||
newValue: obj[v.Code] ? obj[v.Code] : '--',
|
||||
oldValue: upObj[v.Code].length > 0 ? upObj[v.Code] : '--'
|
||||
}
|
||||
@@ -1051,21 +1051,21 @@ export default {
|
||||
if (row.OptType === 'Add' || row.OptType === 'Init') {
|
||||
item = {
|
||||
key: o[v.ChildDataLabel],
|
||||
Enum: o[v.ChildDataLabel],
|
||||
Enum: this.$i18n.locale === 'zh' ? o[v.ChildDataLabel] : o[v.ChildDataEnLabel] ? o[v.ChildDataEnLabel] : o[v.ChildDataLabel],
|
||||
newValue: o[v.ChildDataValue] ? (o[v.ChildDataValue] ? o[v.ChildDataValue] : '--') : '--',
|
||||
oldValue: ''
|
||||
}
|
||||
} else if (row.OptType === 'Delete') {
|
||||
item = {
|
||||
key: o[v.ChildDataLabel],
|
||||
Enum: o[v.ChildDataLabel],
|
||||
Enum: this.$i18n.locale === 'zh' ? o[v.ChildDataLabel] : o[v.ChildDataEnLabel] ? o[v.ChildDataEnLabel] : o[v.ChildDataLabel],
|
||||
oldValue: o[v.ChildDataValue] ? (o[v.ChildDataValue] ? o[v.ChildDataValue] : '--') : '--',
|
||||
newValue: '--'
|
||||
}
|
||||
} else {
|
||||
item = {
|
||||
key: o[v.ChildDataLabel],
|
||||
Enum: o[v.ChildDataLabel],
|
||||
Enum: this.$i18n.locale === 'zh' ? o[v.ChildDataLabel] : o[v.ChildDataEnLabel] ? o[v.ChildDataEnLabel] : o[v.ChildDataLabel],
|
||||
newValue: o[v.ChildDataValue] ? (o[v.ChildDataValue] ? o[v.ChildDataValue] : '--') : '--',
|
||||
oldValue: uo ? uo[v.ChildDataValue] : '--'
|
||||
}
|
||||
@@ -1098,7 +1098,7 @@ export default {
|
||||
item.IsTableFiled = v.IsTableFiled
|
||||
item.DataType = v.DataType
|
||||
item.key = v.Code
|
||||
item.Enum = v.ValueCN
|
||||
item.Enum = this.$i18n.locale === 'zh' ? v.ValueCN : v.Value
|
||||
this[auditData].push(item)
|
||||
return
|
||||
}
|
||||
@@ -1107,14 +1107,14 @@ export default {
|
||||
var body = []
|
||||
v.TableConfigList.forEach((j, i) => {
|
||||
if (j.IsFixedColumn) {
|
||||
head.push({IsPicture: j.IsPicture, headName: j.FixedColumnName, IsMerge: j.IsMerge, ColumnName: j.ColumnName, ColumnValue: j.ColumnValue, ListName: j.ListName, MergeColumnName: j.IsMerge ? j.MergeColumnName : null, ChildrenList: []})
|
||||
head.push({IsPicture: j.IsPicture, headName: this.$i18n.locale === 'zh' ? j.FixedColumnName : j.FixedColumnEnName, IsMerge: j.IsMerge, ColumnName: j.ColumnName, ColumnValue: j.ColumnValue, ListName: j.ListName, MergeColumnName: j.IsMerge ? this.$i18n.locale === 'zh' ? j.MergeColumnName : j.MergeColumnEnName : null, ChildrenList: []})
|
||||
} else {
|
||||
if (j.ListName) {
|
||||
obj[v.Code][0][j.ListName].forEach((x, o) => {
|
||||
head.push({IsPicture: j.IsPicture, headName: x[j.ColumnName], IsMerge: j.IsMerge, ColumnName: j.ColumnName, ColumnValue: j.ColumnValue, ListName: j.ListName, MergeColumnName: j.IsMerge ? j.MergeColumnName : null, ChildrenList: []})
|
||||
head.push({IsPicture: j.IsPicture, headName: x[this.$i18n.locale === 'zh' ? j.ColumnName : j.ColumnEnName ? j.ColumnEnName : j.ColumnName], IsMerge: j.IsMerge, ColumnName: j.ColumnName, ColumnValue: j.ColumnValue, ListName: j.ListName, MergeColumnName: j.IsMerge ? this.$i18n.locale === 'zh' ? j.MergeColumnName : j.MergeColumnEnName : null, ChildrenList: []})
|
||||
})
|
||||
} else {
|
||||
head.push({IsPicture: j.IsPicture, headName: j.ColumnName, IsMerge: j.IsMerge, ColumnName: j.ColumnName, ColumnValue: j.ColumnValue, ListName: j.ListName, MergeColumnName: j.IsMerge ? j.MergeColumnName : null, ChildrenList: []})
|
||||
head.push({IsPicture: j.IsPicture, headName: this.$i18n.locale === 'zh' ? j.ColumnName : j.ColumnEnName ? j.ColumnEnName : j.ColumnName, IsMerge: j.IsMerge, ColumnName: j.ColumnName, ColumnValue: j.ColumnValue, ListName: j.ListName, MergeColumnName: j.IsMerge ? this.$i18n.locale === 'zh' ? j.MergeColumnName : j.MergeColumnEnName : null, ChildrenList: []})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+487
-282
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -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',
|
||||
|
||||
Reference in New Issue
Block a user