Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| a66e15eb39 | |||
| 895e3a6bed | |||
| 9dddc0c012 | |||
| a965f08a1e | |||
| 9962b1a829 | |||
| 049128b90e | |||
| 45e6a20988 | |||
| 5141eb5cbd | |||
| 073b06a76f | |||
| 20723e8d2c | |||
| fba00157a1 | |||
| f0e6708533 | |||
| e770dc1078 | |||
| e15934d7ba | |||
| 4baf039d71 | |||
| 5c4bc96a26 | |||
| 30f9e807b7 | |||
| 269f9f9477 | |||
| 810c786512 | |||
| e27705eb22 | |||
| 83bf082c43 | |||
| 37f12b30cc | |||
| f045f68115 | |||
| 64e67ad106 | |||
| f2ee666083 | |||
| 8ece8915ff | |||
| 8270841ca1 | |||
| e99c4527b9 | |||
| e295bff859 | |||
| 7a53a75038 | |||
| d96822818c | |||
| 9e2255e324 | |||
| dbdd18dcf6 | |||
| 4ae2504278 | |||
| 6a0a5f4724 | |||
| ee2e33405c | |||
| 286865ba8f | |||
| 75a0f3a91a | |||
| 4fbcd8f8f5 | |||
| 3c2edbffc5 | |||
| 38fb56e09e | |||
| 105537c49e | |||
| 355f6bcf86 | |||
| d6e9f9ddc2 | |||
| 16e005e664 | |||
| b92b55a45a | |||
| 0ed070ecd7 | |||
| 49940ab034 | |||
| aca5b0c721 | |||
| 8ea7540581 | |||
| ec6a72e143 | |||
| f512c1456a | |||
| 4aa74b5420 | |||
| 50c37824aa | |||
| 358864c6c6 | |||
| e2db9c2d51 | |||
| 78fbae1c1f | |||
| 26c58f14fa | |||
| f8774224b3 | |||
| bc41f4b4c1 | |||
| 0280dfb959 | |||
| 49aa98af9f | |||
| 9ce6ff25b9 | |||
| fca8c1c9bf | |||
| d0ebc3e791 | |||
| ea4f23fb16 | |||
| 01d01b1126 | |||
| 040d9309b9 | |||
| 1d6656a5b8 | |||
| 76e328dcca | |||
| 9852d99a4a | |||
| 39f7ba7181 | |||
| fb68892cd4 | |||
| 1e6ec0df27 | |||
| 4ff6416edb | |||
| b2645f6423 | |||
| 122c76d9b2 | |||
| 2d155612e5 | |||
| 329d6b1ff6 | |||
| 7006cf849e | |||
| 71f3519769 | |||
| bbf2dd16e6 | |||
| 520d499a0b | |||
| 00cfb92087 | |||
| 8eb0b96c8e | |||
| 24b9120a0a | |||
| 02fcc4a2c1 | |||
| f53412acbf | |||
| 3948596014 | |||
| e899c0814e | |||
| d12b4adb68 | |||
| 3551a521c8 | |||
| e80d439377 | |||
| f499557c01 | |||
| ecaca550ab | |||
| b7d7b93c4a | |||
| 7bf92c60ea | |||
| 36a08d1055 | |||
| 5ebf9032a5 | |||
| 1896c58b50 | |||
| 9168ef3ad7 | |||
| 4ad299e243 | |||
| 5d337b0b26 | |||
| ca579f8731 | |||
| 92d41dff28 | |||
| 8d6ae3a49f | |||
| 18f23d2bba | |||
| 0a428bf954 | |||
| a6b5d0b196 | |||
| 8bf6d5f515 | |||
| 74f3852ecc | |||
| 9408ce12e2 | |||
| 06a2361ea0 | |||
| e3313edefd | |||
| 2676ff4295 | |||
| 41b3a98594 | |||
| c2aba6c3fe | |||
| 81a5d5af17 | |||
| 23ac15f978 | |||
| 1ec4c25472 | |||
| ac8710b26b | |||
| 1130b55677 | |||
| fb57dfe90c | |||
| 2784958ccb | |||
| d6a3bcba30 | |||
| 4ff9a7c482 | |||
| 33b3818a9e | |||
| 38c31af137 | |||
| fb671defb5 | |||
| a25aa2482f | |||
| 4249ccd9d6 | |||
| 9a88930a04 | |||
| aea6a3f8c8 | |||
| c657bb8783 | |||
| b0ae3cbd27 | |||
| 10487640cd | |||
| 83fa937537 | |||
| dd1fb94562 | |||
| 116402f865 | |||
| 76fe08ed23 | |||
| 993d97e205 | |||
| 11471525af | |||
| 600abc3ce1 | |||
| 9609768e5e | |||
| ce565e00ff | |||
| e49fe23396 | |||
| 85463ad240 | |||
| fc228622e1 | |||
| 8840ddc77a | |||
| 3b31132616 | |||
| c7df59e564 | |||
| aeef8eaacf | |||
| b0c4cfd0bf | |||
| 38c06595aa | |||
| a0c5c7d304 | |||
| 2323cbdd27 | |||
| c2f3e02ef1 | |||
| b069c881f2 | |||
| faaaf8f28f | |||
| 1e5bd46a40 | |||
| 7d2af46845 | |||
| e1c41d2327 | |||
| d4ae366fa6 | |||
| e0321bae72 | |||
| 1e720e399d | |||
| 1368397da9 | |||
| c8c049b5d0 |
+2
-1
@@ -5,7 +5,8 @@ NODE_ENV = 'development'
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
VUE_APP_IS_TEST = false
|
||||
|
||||
# onlyoffice地址
|
||||
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
|
||||
# base api
|
||||
VUE_APP_BASE_API = 'http://123.56.94.154:7000'
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ NODE_ENV = 'prod'
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
# onlyoffice地址
|
||||
VUE_APP_ONLYOFFICE_URL = "https://office.extimaging.com"
|
||||
|
||||
# 是否开启登陆限制 true:是 false:否
|
||||
VUE_APP_LOGIN_FOR_PERMISSION = true
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@ ENV = 'production'
|
||||
NODE_ENV = 'production'
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
# onlyoffice地址
|
||||
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
|
||||
|
||||
VUE_APP_IS_TEST = true
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ NODE_ENV = 'production'
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
# onlyoffice地址
|
||||
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
|
||||
|
||||
# base public path
|
||||
VUE_APP_BASE_PATH = '/'
|
||||
|
||||
|
||||
+2
-2
@@ -252,7 +252,7 @@ export default {
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
this.$confirm('确定修改当前页面国际化内容?')
|
||||
this.$confirm(this.$t("i18n:confirm:updatei18n"))
|
||||
.then(() => {
|
||||
batchAddOrUpdateFrontInternationalization(this.tableData).then(
|
||||
async (res) => {
|
||||
@@ -270,7 +270,7 @@ export default {
|
||||
i18n.mergeLocaleMessage('zh', zhMessages)
|
||||
i18n.mergeLocaleMessage('en', enMessages)
|
||||
this.drawer = false
|
||||
this.$message.success('国际化修改成功')
|
||||
this.$message.success(this.$t("i18n:message:updatei18nSuccessfully"))
|
||||
if (this.il8nExternal) {
|
||||
this.$EventBus.$emit('il8nUpdate')
|
||||
}
|
||||
|
||||
+14
-1
@@ -212,7 +212,20 @@ export function getSystemDocumentList(param) {
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
export function publishSystemDocument(param) {
|
||||
return request({
|
||||
url: `/SystemDocument/publishSystemDocument`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function outLineSystemDocument(param) {
|
||||
return request({
|
||||
url: `/SystemDocument/outLineSystemDocument`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function addOrUpdateSystemDocument(param) {
|
||||
return request({
|
||||
url: `/SystemDocument/addOrUpdateSystemDocument`,
|
||||
|
||||
@@ -178,6 +178,15 @@ export function pMTrainingRecordList_Export(data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出系统培训记录
|
||||
export function getSysDocumentConfirmList_Export(data) {
|
||||
return requestDownload({
|
||||
url: `/ExcelExport/getSysDocumentConfirmList_Export`,
|
||||
responseType: 'blob',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出影像指控
|
||||
export function qCVisitList_Export(data) {
|
||||
return requestDownload({
|
||||
|
||||
@@ -346,9 +346,9 @@ export function getReReadingOrBackInfluenceTaskList(taskId, isReReading, applyId
|
||||
})
|
||||
}
|
||||
|
||||
export function PMSetTaskBack(trialId, taskId) {
|
||||
export function PMSetTaskBack(trialId, taskId, pmBackReason) {
|
||||
return request({
|
||||
url: `/VisitTask/PMSetTaskBack/${trialId}/${taskId}`,
|
||||
url: `/VisitTask/PMSetTaskBack/${trialId}/${taskId}/${pmBackReason}`,
|
||||
method: 'put'
|
||||
})
|
||||
}
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
<template>
|
||||
<div class="preview-wrapper">
|
||||
<iframe
|
||||
v-if="fileType.indexOf('jpg') !== -1 || fileType.indexOf('png') !== -1"
|
||||
frameborder="0"
|
||||
:src="filePath"
|
||||
width="100%"
|
||||
height="100%"
|
||||
/>
|
||||
<iframe v-if="fileType.indexOf('jpg') !== -1 || fileType.indexOf('png') !== -1" frameborder="0" :src="filePath"
|
||||
width="100%" height="100%" />
|
||||
<!-- <embed v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" style="width: 100%; height: 100%"> -->
|
||||
<!-- <iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" width="100%" height="100%" frameborder="0" /> -->
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1"
|
||||
:src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`"
|
||||
width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<!-- <pdf-->
|
||||
<!-- v-else-if="fileType.indexOf('pdf') !== -1"-->
|
||||
<!-- :src="`/static/pdfjs/web/viewer.html?file=${filePath}`">-->
|
||||
<!-- </pdf>-->
|
||||
<div v-else>
|
||||
<iframe v-else
|
||||
:src="`/static/onlyOffice/viewer.html?url=${OSSclientConfig.basePath}${filePath}?onlyOffice_url=${onlyOffice_url}&type=${fileType}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
|
||||
width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<!-- <div v-else>
|
||||
{{ $t('common:message:downloadFile') }}
|
||||
<el-link type="primary" @click="downLoadFile">{{ $t('common:button:download') }}</el-link>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import DOCUMENTTYPE from "@/utils/onlyOffice_type.js"
|
||||
export default {
|
||||
name: 'PreviewFile',
|
||||
computed: {
|
||||
@@ -36,12 +36,23 @@ export default {
|
||||
fileType: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY:process.env.VUE_APP_COMPANY_NAME
|
||||
COMPANY: process.env.VUE_APP_COMPANY_NAME,
|
||||
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
documentType() {
|
||||
console.log(DOCUMENTTYPE[`.${this.fileType}`], 'documentType')
|
||||
return DOCUMENTTYPE[`.${this.fileType}`]
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -62,14 +73,16 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.preview-wrapper{
|
||||
.preview-wrapper {
|
||||
height: 100%;
|
||||
width:100%;
|
||||
width: 100%;
|
||||
padding: 10px;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
custom-class="base-dialog-wrapper" @close="handleClose">
|
||||
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
||||
<iframe v-if="visible"
|
||||
:src="`/static/onlyOffice/viewer.html?url=${OSSclientConfig.basePath}${path}?type=${type}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
|
||||
:src="`/static/onlyOffice/viewer.html?url=${OSSclientConfig.basePath}${path}?onlyOffice_url=${onlyOffice_url}&type=${type}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
|
||||
width="100%" height="99%" frameborder="0" crossorigin="anonymous" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
@@ -20,6 +20,7 @@ export default {
|
||||
title: null,
|
||||
documentType: null,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
|
||||
@@ -310,6 +310,11 @@ async function VueInit() {
|
||||
text = text.replace(test, item.TrialName)
|
||||
})
|
||||
}
|
||||
let CompanyInfo = JSON.parse(localStorage.getItem('CompanyInfo'))
|
||||
if(CompanyInfo&&CompanyInfo.SystemShortName){
|
||||
let test = new RegExp('IRC', 'ig')
|
||||
text = text.replace(test, CompanyInfo.SystemShortName)
|
||||
}
|
||||
// return i18n.t(key)
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -68,6 +68,12 @@ body .el-table th.gutter {
|
||||
}
|
||||
}
|
||||
|
||||
.text-ellipsis {
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.el-loading-mask {
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
+137
-10
@@ -39,6 +39,108 @@ function getNumberValues(dataSet, tag, minimumLength) {
|
||||
|
||||
return values;
|
||||
}
|
||||
function getLutDescriptor(dataSet, tag) {
|
||||
if (!dataSet.elements[tag] || dataSet.elements[tag].length !== 6) {
|
||||
return;
|
||||
}
|
||||
|
||||
return [
|
||||
dataSet.uint16(tag, 0),
|
||||
dataSet.uint16(tag, 1),
|
||||
dataSet.uint16(tag, 2),
|
||||
];
|
||||
}
|
||||
|
||||
function getLutData(lutDataSet, tag, lutDescriptor) {
|
||||
const lut = [];
|
||||
const lutData = lutDataSet.elements[tag];
|
||||
|
||||
for (let i = 0; i < lutDescriptor[0]; i++) {
|
||||
// Output range is always unsigned
|
||||
if (lutDescriptor[2] === 16) {
|
||||
lut[i] = lutDataSet.uint16(tag, i);
|
||||
} else {
|
||||
lut[i] = lutDataSet.byteArray[i + lutData.dataOffset];
|
||||
}
|
||||
}
|
||||
|
||||
return lut;
|
||||
}
|
||||
function populateSmallestLargestPixelValues(dataSet, imagePixelModule) {
|
||||
const pixelRepresentation = dataSet.uint16('x00280103');
|
||||
if (pixelRepresentation === 0) {
|
||||
imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106');
|
||||
imagePixelModule.largestPixelValue = dataSet.uint16('x00280107');
|
||||
} else {
|
||||
imagePixelModule.smallestPixelValue = dataSet.int16('x00280106');
|
||||
imagePixelModule.largestPixelValue = dataSet.int16('x00280107');
|
||||
}
|
||||
imagePixelModule.largestPixelValue = imagePixelModule.largestPixelValue === 0 ? undefined : imagePixelModule.largestPixelValue;
|
||||
}
|
||||
function populatePaletteColorLut(dataSet, imagePixelModule) {
|
||||
imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
|
||||
dataSet,
|
||||
'x00281101'
|
||||
);
|
||||
imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
|
||||
dataSet,
|
||||
'x00281102'
|
||||
);
|
||||
imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
|
||||
dataSet,
|
||||
'x00281103'
|
||||
);
|
||||
|
||||
// The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
|
||||
// When the number of table entries is equal to 2ˆ16 then this value shall be 0.
|
||||
// See http://dicom.nema.org/MEDICAL/DICOM/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.5
|
||||
if (imagePixelModule.redPaletteColorLookupTableDescriptor[0] === 0) {
|
||||
imagePixelModule.redPaletteColorLookupTableDescriptor[0] = 65536;
|
||||
imagePixelModule.greenPaletteColorLookupTableDescriptor[0] = 65536;
|
||||
imagePixelModule.bluePaletteColorLookupTableDescriptor[0] = 65536;
|
||||
}
|
||||
|
||||
// The third Palette Color Lookup Table Descriptor value specifies the number of bits for each entry in the Lookup Table Data.
|
||||
// It shall take the value of 8 or 16.
|
||||
// The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1.
|
||||
// The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors.
|
||||
//
|
||||
// Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits;
|
||||
// this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry.
|
||||
// The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16.
|
||||
const numLutEntries =
|
||||
imagePixelModule.redPaletteColorLookupTableDescriptor[0];
|
||||
const lutData = dataSet.elements.x00281201;
|
||||
const lutBitsAllocated = lutData.length === numLutEntries ? 8 : 16;
|
||||
|
||||
// If the descriptors do not appear to have the correct values, correct them
|
||||
if (
|
||||
imagePixelModule.redPaletteColorLookupTableDescriptor[2] !==
|
||||
lutBitsAllocated
|
||||
) {
|
||||
imagePixelModule.redPaletteColorLookupTableDescriptor[2] = lutBitsAllocated;
|
||||
imagePixelModule.greenPaletteColorLookupTableDescriptor[2] =
|
||||
lutBitsAllocated;
|
||||
imagePixelModule.bluePaletteColorLookupTableDescriptor[2] =
|
||||
lutBitsAllocated;
|
||||
}
|
||||
|
||||
imagePixelModule.redPaletteColorLookupTableData = getLutData(
|
||||
dataSet,
|
||||
'x00281201',
|
||||
imagePixelModule.redPaletteColorLookupTableDescriptor
|
||||
);
|
||||
imagePixelModule.greenPaletteColorLookupTableData = getLutData(
|
||||
dataSet,
|
||||
'x00281202',
|
||||
imagePixelModule.greenPaletteColorLookupTableDescriptor
|
||||
);
|
||||
imagePixelModule.bluePaletteColorLookupTableData = getLutData(
|
||||
dataSet,
|
||||
'x00281203',
|
||||
imagePixelModule.bluePaletteColorLookupTableDescriptor
|
||||
);
|
||||
}
|
||||
function metaDataProvider(type, imageId) {
|
||||
const parsedImageId = parseImageId(imageId);
|
||||
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
|
||||
@@ -100,7 +202,7 @@ function metaDataProvider(type, imageId) {
|
||||
};
|
||||
}
|
||||
if (type === 'imagePixelModule') {
|
||||
return {
|
||||
const imagePixelModule = {
|
||||
samplesPerPixel: dataSet.uint16('x00280002'),
|
||||
photometricInterpretation: dataSet.string('x00280004'),
|
||||
rows: dataSet.uint16('x00280010'),
|
||||
@@ -110,16 +212,41 @@ function metaDataProvider(type, imageId) {
|
||||
highBit: dataSet.uint16('x00280102'),
|
||||
pixelRepresentation: dataSet.uint16('x00280103'),
|
||||
planarConfiguration: dataSet.uint16('x00280006'),
|
||||
pixelAspectRatio: dataSet.uint16('x00280034'),
|
||||
smallestPixelValue: null,
|
||||
largestPixelValue: null,
|
||||
redPaletteColorLookupTableDescriptor: dataSet.string('x00281101'),
|
||||
greenPaletteColorLookupTableDescriptor: dataSet.string('x00281102'),
|
||||
bluePaletteColorLookupTableDescriptor: dataSet.string('x00281103'),
|
||||
redPaletteColorLookupTableData: dataSet.string('x00281201'),
|
||||
greenPaletteColorLookupTableData: dataSet.string('x00281202'),
|
||||
bluePaletteColorLookupTableData: dataSet.string('x00281203')
|
||||
pixelAspectRatio: dataSet.string('x00280034'),
|
||||
};
|
||||
populateSmallestLargestPixelValues(dataSet, imagePixelModule);
|
||||
|
||||
if (
|
||||
imagePixelModule.photometricInterpretation === 'PALETTE COLOR' &&
|
||||
dataSet.elements.x00281101
|
||||
) {
|
||||
populatePaletteColorLut(dataSet, imagePixelModule);
|
||||
}
|
||||
return imagePixelModule;
|
||||
}
|
||||
// if (type === 'imagePixelModule') {
|
||||
// return {
|
||||
// samplesPerPixel: dataSet.uint16('x00280002'),
|
||||
// photometricInterpretation: dataSet.string('x00280004'),
|
||||
// rows: dataSet.uint16('x00280010'),
|
||||
// columns: dataSet.uint16('x00280011'),
|
||||
// bitsAllocated: dataSet.uint16('x00280100'),
|
||||
// bitsStored: dataSet.uint16('x00280101'),
|
||||
// highBit: dataSet.uint16('x00280102'),
|
||||
// pixelRepresentation: dataSet.uint16('x00280103'),
|
||||
// planarConfiguration: dataSet.uint16('x00280006'),
|
||||
// pixelAspectRatio: dataSet.uint16('x00280034'),
|
||||
// smallestPixelValue: null,
|
||||
// largestPixelValue: null,
|
||||
// // smallestPixelValue: dataSet.uint16('x00280106'),
|
||||
// // largestPixelValue: dataSet.uint16('x00280107'),
|
||||
// redPaletteColorLookupTableDescriptor: dataSet.string('x00281101'),
|
||||
// greenPaletteColorLookupTableDescriptor: dataSet.string('x00281102'),
|
||||
// bluePaletteColorLookupTableDescriptor: dataSet.string('x00281103'),
|
||||
// redPaletteColorLookupTableData: dataSet.string('x00281201'),
|
||||
// greenPaletteColorLookupTableData: dataSet.string('x00281202'),
|
||||
// bluePaletteColorLookupTableData: dataSet.string('x00281203')
|
||||
// }
|
||||
// }
|
||||
}
|
||||
export default metaDataProvider;
|
||||
@@ -21,7 +21,7 @@ service.interceptors.request.use(
|
||||
async config => {
|
||||
path = router && router.app && router.app._route && router.app._route.path
|
||||
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
||||
config.baseURL = process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api'
|
||||
// config.baseURL = process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api'
|
||||
config.headers['Self-Referer'] = window.location.href
|
||||
var language = zzSessionStorage.getItem('lang')
|
||||
config.headers['Accept-Language'] = language === 'en' ? 'en-US,en;q=0.5' : 'zh-CN,zh;q=0.9'
|
||||
|
||||
@@ -36,10 +36,10 @@
|
||||
<el-input-number v-model="form.SignViewMinimumMinutes" controls-position="right" :min="1" :max="50" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:signature:form:CurrentStaffTrainDays')" prop="CurrentStaffTrainDays">
|
||||
<el-input-number v-model="form.CurrentStaffTrainDays" controls-position="right" :min="1" :max="1000" />
|
||||
<el-input-number v-model="form.CurrentStaffTrainDays" controls-position="right" :min="0" :max="1000" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:signature:form:NewStaffTrainDays')" prop="NewStaffTrainDays">
|
||||
<el-input-number v-model="form.NewStaffTrainDays" controls-position="right" :min="1" :max="1000" />
|
||||
<el-input-number v-model="form.NewStaffTrainDays" controls-position="right" :min="0" :max="1000" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item v-if="form.Id !== ''" label="是否废除: ">
|
||||
<el-radio-group v-model="form.IsDeleted">
|
||||
@@ -77,11 +77,12 @@ export default {
|
||||
FileTypeId: '',
|
||||
Name: '',
|
||||
Path: '',
|
||||
IsDeleted: false,
|
||||
IsPublish: false,
|
||||
IsDeleted: true,
|
||||
SignViewMinimumMinutes: null,
|
||||
DocUserSignType: 0,
|
||||
CurrentStaffTrainDays: null,
|
||||
NewStaffTrainDays: null,
|
||||
CurrentStaffTrainDays: 1,
|
||||
NewStaffTrainDays: 14,
|
||||
},
|
||||
rules: {
|
||||
FileTypeId: [
|
||||
@@ -137,8 +138,11 @@ export default {
|
||||
this.form.Name = this.data.Name
|
||||
this.form.Path = this.data.Path
|
||||
this.form.IsDeleted = this.data.IsDeleted
|
||||
this.form.IsPublish = this.data.IsPublish
|
||||
this.form.SignViewMinimumMinutes = this.data.SignViewMinimumMinutes
|
||||
this.form.DocUserSignType = this.data.DocUserSignType
|
||||
this.form.CurrentStaffTrainDays = this.data.CurrentStaffTrainDays
|
||||
this.form.NewStaffTrainDays = this.data.NewStaffTrainDays
|
||||
}
|
||||
this.loading = false
|
||||
},
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
:http-request="handleUploadFile" :on-preview="handlePreview" :on-remove="handleRemoveFile"
|
||||
:show-file-list="true" :file-list="fileList" :limit="1" :on-exceed="handleExceed">
|
||||
<el-button size="small" type="primary" :loading="btnLoading">{{ $t('common:button:check')
|
||||
}}</el-button>
|
||||
}}</el-button>
|
||||
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
|
||||
({{ $t('trials:signature:label:type').replace("xxx", this.accept.join(", ")) }})
|
||||
</span>
|
||||
@@ -58,7 +58,7 @@ export default {
|
||||
FilePath: null,
|
||||
FileSize: null,
|
||||
OffLine: false,
|
||||
SystemDocumentId: null
|
||||
SystemDocumentId: null,
|
||||
},
|
||||
rules: {
|
||||
Name: [
|
||||
@@ -128,6 +128,7 @@ export default {
|
||||
path: this.$getObjectName(res.url),
|
||||
url: this.$getObjectName(res.url),
|
||||
})
|
||||
this.form.Name = param.file.name
|
||||
this.form.FileName = param.file.name
|
||||
this.form.FilePath = this.$getObjectName(res.url)
|
||||
this.form.FileSize = param.file.size
|
||||
|
||||
@@ -2,7 +2,12 @@
|
||||
<div v-if="config.visible">
|
||||
<base-model :config="config">
|
||||
<template slot="dialog-body">
|
||||
<el-button size="mini" type="primary" style="float:right" @click.stop="edit({})">
|
||||
<el-form ref="form" :model="rowData" label-width="80px" style="width: 80%;display: inline-block;">
|
||||
<el-form-item :label="`${$t('dictionary:signature:table:Name')}: `">
|
||||
<span class="name text-ellipsis" :title="rowData.Name">{{ rowData.Name }}</span>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button size="mini" type="primary" style="float:right" @click.stop="edit({})" v-if="!isView">
|
||||
{{ $t('common:button:add') }}</el-button>
|
||||
<el-table :data="list" style="width: 100%" max-height="300px" v-loading="loading"
|
||||
@sort-change="handleSortByColumn">
|
||||
@@ -10,7 +15,7 @@
|
||||
<el-table-column prop="Name" :label="$t('dictionary:signature:attachmentList:FileName')"
|
||||
sortable="custom" />
|
||||
<el-table-column prop="OffLine" :label="$t('dictionary:signature:attachmentList:OffLine')"
|
||||
sortable="custom">
|
||||
sortable="custom" v-if="!isView">
|
||||
<template slot-scope="scope">
|
||||
<el-switch v-model="scope.row.OffLine" @change="(val) => OffLine(scope.row, val)"
|
||||
:active-value="true" :inactive-value="false" :active-text="$fd('YesOrNo', true)"
|
||||
@@ -25,14 +30,14 @@
|
||||
<el-button size="mini" type="text" @click.stop="preview(scope.row)">
|
||||
{{ $t('common:button:preview') }}
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" @click.stop="edit(scope.row)">
|
||||
<el-button size="mini" type="text" @click.stop="edit(scope.row)" v-if="!isView">
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" @click.stop="OffLine(scope.row, true)"
|
||||
<!-- <el-button size="mini" type="text" @click.stop="OffLine(scope.row, true)"
|
||||
:disabled="scope.row.OffLine">
|
||||
{{ $t('dictionary:signature:attachmentList:OffLine') }}
|
||||
</el-button>
|
||||
<el-button size="mini" type="text" @click.stop="del(scope.row)">
|
||||
</el-button> -->
|
||||
<el-button size="mini" type="text" @click.stop="del(scope.row)" v-if="!isView">
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -52,25 +57,30 @@
|
||||
|
||||
<img v-show="false" :src="`${OSSclientConfig.basePath}${rowData.FilePath}`" alt="Image" />
|
||||
</viewer>
|
||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible"
|
||||
v-if="perview_visible" />
|
||||
<!-- <attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible"
|
||||
v-if="perview_visible" /> -->
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import BaseModel from '@/components/BaseModel'
|
||||
import attachmentForm from './attachmentForm'
|
||||
import attachmentPreview from './attachmentPreview'
|
||||
// import attachmentPreview from './attachmentPreview'
|
||||
import { addOrUpdateSystemDocumentAttachment, getSystemDocumentAttachmentList, deleteSystemDocumentAttachment } from '@/api/dictionary'
|
||||
const defaultSearchData = () => {
|
||||
return {
|
||||
PageIndex: 1,
|
||||
PageSize: 1000,
|
||||
Asc: false,
|
||||
OffLine: null,
|
||||
SortField: null
|
||||
}
|
||||
}
|
||||
export default {
|
||||
components: { BaseModel, attachmentForm, attachmentPreview },
|
||||
components: {
|
||||
BaseModel,
|
||||
attachmentForm,
|
||||
// attachmentPreview
|
||||
},
|
||||
props: {
|
||||
config: {
|
||||
type: Object,
|
||||
@@ -82,6 +92,16 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
isView: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
rowData: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
SystemDocumentId: {
|
||||
type: String,
|
||||
default: ''
|
||||
@@ -108,7 +128,7 @@ export default {
|
||||
flipVertical: true,
|
||||
}
|
||||
},
|
||||
perview_visible: false
|
||||
// perview_visible: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -143,6 +163,10 @@ export default {
|
||||
}
|
||||
},
|
||||
edit(row) {
|
||||
this.title = this.$t('dictionary:signature:attachmentForm:title:update')
|
||||
if (!row.Id) {
|
||||
this.title = this.$t('dictionary:signature:attachmentForm:title:add')
|
||||
}
|
||||
this.rowData = Object.assign({}, row)
|
||||
this.visible = true
|
||||
},
|
||||
@@ -151,6 +175,9 @@ export default {
|
||||
if (!this.SystemDocumentId) return false
|
||||
this.loading = true
|
||||
this.searchData.SystemDocumentId = this.SystemDocumentId
|
||||
if (this.isView) {
|
||||
this.searchData.OffLine = false
|
||||
}
|
||||
let res = await getSystemDocumentAttachmentList(this.searchData)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
@@ -179,7 +206,7 @@ export default {
|
||||
}
|
||||
},
|
||||
preview(data) {
|
||||
return this.perview_visible = true
|
||||
// return this.perview_visible = true
|
||||
this.rowData = Object.assign({}, data)
|
||||
if (['.ppt',
|
||||
'.pptx',
|
||||
@@ -222,4 +249,10 @@ export default {
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.name {
|
||||
display: block;
|
||||
width: 90%;
|
||||
}
|
||||
</style>
|
||||
+33
-13
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<el-dialog :visible.sync="visible" :title="title" :fullscreen="true" append-to-body
|
||||
custom-class="base-dialog-wrapper" @close="handleClose">
|
||||
custom-class="base-dialog-wrapper" :before-close="handleClose">
|
||||
<div v-loading="loading" class="img-container" v-if="visible">
|
||||
<el-card class="box-card left">
|
||||
<div class="title">
|
||||
@@ -23,12 +23,8 @@
|
||||
" style="width: 100%; height: 100%"
|
||||
:src="`${OSSclientConfig.basePath}${item.FilePath}?x-oss-process=image/resize,w_50,h_50/format,png`"
|
||||
fit="contain" crossorigin="anonymous" />
|
||||
<el-image v-else-if="item.FileFormat === 'pdf'" style="width: 100%; height: 100%"
|
||||
:src="pdf" fit="contain" crossorigin="anonymous" />
|
||||
<el-image v-else-if="
|
||||
item.FileFormat === 'zip'
|
||||
" style="width: 100%; height: 100%" :src="zip" fit="contain"
|
||||
crossorigin="anonymous" />
|
||||
<el-image v-else style="width: 100%; height: 100%" :src="getsrc(item.FileFormat)"
|
||||
fit="contain" crossorigin="anonymous" />
|
||||
</div>
|
||||
<div v-if="item.Name.length < 15" class="img-text">
|
||||
{{ `${index + 1}. ${item.Name}` }}
|
||||
@@ -52,8 +48,9 @@
|
||||
].includes(rowData.FileFormat)">
|
||||
<imageViewer :rowData="rowData" />
|
||||
</div>
|
||||
<div style="width: 100%; height: 100%" v-else-if="rowData.FileFormat === 'pdf'">
|
||||
<PreviewFile :file-path="rowData.FilePath" :file-type="rowData.FileFormat" />
|
||||
<div style="width: 100%; height: 100%" v-else>
|
||||
<PreviewFile v-if='rowData.FilePath' :file-path="rowData.FilePath" :file-type="rowData.FileFormat"
|
||||
:title="rowData.Name" />
|
||||
</div>
|
||||
</el-card>
|
||||
|
||||
@@ -65,8 +62,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import pdf from '@/assets/pdf.png'
|
||||
import zip from '@/assets/zip.jpg'
|
||||
import pdf from '@/assets/file_icon/pdf.png'
|
||||
import zip from '@/assets/file_icon/zip.png'
|
||||
import doc from '@/assets/file_icon/doc.png'
|
||||
import docx from '@/assets/file_icon/docx.png'
|
||||
import ppt from '@/assets/file_icon/ppt.png'
|
||||
import pptx from '@/assets/file_icon/pptx.png'
|
||||
import xls from '@/assets/file_icon/xls.png'
|
||||
import xlsx from '@/assets/file_icon/xlsx.png'
|
||||
import PreviewFile from '@/components/PreviewFile'
|
||||
import imageViewer from './image-viewer'
|
||||
import { getSystemDocumentAttachmentList } from '@/api/dictionary'
|
||||
@@ -75,6 +78,7 @@ const defaultSearchData = () => {
|
||||
PageIndex: 1,
|
||||
PageSize: 1000,
|
||||
Asc: false,
|
||||
OffLine: null,
|
||||
SortField: null
|
||||
}
|
||||
}
|
||||
@@ -92,16 +96,26 @@ export default {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isView: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
pdf,
|
||||
zip,
|
||||
doc,
|
||||
docx,
|
||||
ppt,
|
||||
pptx,
|
||||
xls,
|
||||
xlsx,
|
||||
rowData: {},
|
||||
list: [],
|
||||
searchData: defaultSearchData(),
|
||||
title: null
|
||||
title: this.$t('dictionary:signature:fileList')
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -113,6 +127,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getsrc(type) {
|
||||
return this[type.toLowerCase()]
|
||||
},
|
||||
selected(row) {
|
||||
this.rowData = row
|
||||
},
|
||||
@@ -124,11 +141,14 @@ export default {
|
||||
if (!this.SystemDocumentId) return false
|
||||
this.loading = true
|
||||
this.searchData.SystemDocumentId = this.SystemDocumentId
|
||||
if (this.isView) {
|
||||
this.searchData.OffLine = false
|
||||
}
|
||||
let res = await getSystemDocumentAttachmentList(this.searchData)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.rowData = this.list[0]
|
||||
this.rowData = this.list[0] || {}
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
|
||||
@@ -44,10 +44,6 @@ export default {
|
||||
type: Function,
|
||||
default: () => { },
|
||||
},
|
||||
zipImg: {
|
||||
required: true,
|
||||
default: '',
|
||||
},
|
||||
rowData:{
|
||||
type: Object,
|
||||
default: () => {
|
||||
|
||||
@@ -20,8 +20,7 @@
|
||||
<el-form :inline="true" size="small">
|
||||
<el-form-item :label="$t('dictionary:signature:search:FileTypeId')">
|
||||
<el-select v-model="searchData.FileTypeId" style="width: 150px" clearable>
|
||||
<el-option v-for="item of dict.type.Sys_Document" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
<el-option v-for="item of $d.Sys_Document" :key="item.id" :label="item.label" :value="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:signature:search:Name')">
|
||||
@@ -60,19 +59,37 @@
|
||||
<el-button type="primary" size="small" @click="handleAdd">
|
||||
{{ $t('common:button:new') }}
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" :disabled="multipleSelection.length <= 0"
|
||||
@click="publishSystemDocument(multipleSelection)">
|
||||
{{ $t('dictionary:signature:button:publish') }}
|
||||
</el-button>
|
||||
<el-button type="primary" size="small" :disabled="multipleSelection.length <= 0"
|
||||
@click="handleRepeal(multipleSelection)">
|
||||
{{ $t('common:button:revoke') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="loading" :data="list" stripe height="100"
|
||||
@sort-change="handleSortByColumn">
|
||||
<el-table-column type="index" width="40" />
|
||||
@sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
|
||||
<!-- <el-table-column type="index" width="40" /> -->
|
||||
<el-table-column type="selection" width="55" :selectable="handleSelectable">
|
||||
</el-table-column>
|
||||
<el-table-column prop="FileType" :label="$t('dictionary:signature:table:FileType')" show-overflow-tooltip
|
||||
sortable="custom" min-width="120px" />
|
||||
<el-table-column prop="Name" :label="$t('dictionary:signature:table:Name')" show-overflow-tooltip
|
||||
sortable="custom" min-width="120px" />
|
||||
|
||||
<el-table-column prop="AttachmentCount" :label="$t('dictionary:signature:table:AttachmentCount')"
|
||||
show-overflow-tooltip sortable="custom" min-width="150px">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">
|
||||
{{ scope.row.AttachmentCount }}
|
||||
<i class="el-icon-upload2" />
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="SignViewMinimumMinutes" :label="$t('dictionary:signature:table:SignViewMinimumMinutes')"
|
||||
show-overflow-tooltip sortable="custom" min-width="200px" />
|
||||
<el-table-column prop="CurrentStaffTrainDays" :label="$t('dictionary:signature:table:CurrentStaffTrainDays')"
|
||||
@@ -100,34 +117,39 @@
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="IsPublish" :label="$t('dictionary:signature:table:IsPublish')" show-overflow-tooltip
|
||||
sortable="custom" min-width="120px">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="scope.row.IsPublish ? 'primary' : 'danger'">{{
|
||||
$fd('AttachmentPublishStatus', scope.row.IsPublish)
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="DocUserSignType" :label="$t('dictionary:signature:table:DocUserSignType')"
|
||||
show-overflow-tooltip sortable="custom" min-width="150px">
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('ReadingYesOrNo', Number(scope.row.DocUserSignType)) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="AttachmentCount" :label="$t('dictionary:signature:table:AttachmentCount')"
|
||||
show-overflow-tooltip sortable="custom" min-width="150px">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row)">{{ scope.row.AttachmentCount }}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="CreateTime" :label="$t('dictionary:signature:table:CreateTime')" show-overflow-tooltip
|
||||
sortable="custom" min-width="180px" />
|
||||
|
||||
<el-table-column :label="$t('common:action:action')" min-width="180px" fixed="right">
|
||||
<el-table-column :label="$t('common:action:action')" min-width="240px" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="handlePreview(scope.row)">
|
||||
{{ $t('common:button:preview') }}
|
||||
<el-button circle icon="el-icon-view" @click="handlePreview(scope.row)"
|
||||
:title="$t('common:button:preview')">
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleEdit(scope.row)">
|
||||
{{ $t('common:button:edit') }}
|
||||
<el-button circle icon="el-icon-edit-outline" :title="$t('common:button:edit')"
|
||||
@click="handleEdit(scope.row)">
|
||||
</el-button>
|
||||
<el-button :disabled="scope.row.IsDeleted" type="text" @click="handleRepeal(scope.row)">
|
||||
{{ $t('common:button:revoke') }}
|
||||
<el-button :disabled="scope.row.IsPublish" circle icon="el-icon-position"
|
||||
:title="$t('dictionary:signature:button:publish')" @click="publishSystemDocument([scope.row])">
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">
|
||||
{{ $t('common:button:delete') }}
|
||||
<el-button :disabled="scope.row.IsDeleted" circle icon="el-icon-close" :title="$t('common:button:revoke')"
|
||||
@click="handleRepeal([scope.row])">
|
||||
</el-button>
|
||||
<el-button circle icon="el-icon-delete" :title="$t('common:button:delete')"
|
||||
@click="handleDelete(scope.row)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -142,10 +164,17 @@
|
||||
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
|
||||
</el-dialog>
|
||||
<!--附件列表-->
|
||||
<attachmentList v-if="config.visible" :config="config" :SystemDocumentId="SystemDocumentId" @getLit="getList" />
|
||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
||||
@getList="getList" />
|
||||
<!-- 预览文件 -->
|
||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible" :isView="true"
|
||||
v-if="perview_visible" />
|
||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="$t('common:button:preview')"
|
||||
:fullscreen="true" append-to-body custom-class="base-dialog-wrapper">
|
||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
||||
$t('trials:signRecords:table:AttachmentCount') }} ({{
|
||||
currentRow.AttachmentCount }})</span>
|
||||
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
||||
<PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" />
|
||||
</div>
|
||||
@@ -154,7 +183,7 @@
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getSystemDocumentList, deleteSystemDocument } from '@/api/dictionary'
|
||||
import { getSystemDocumentList, deleteSystemDocument, publishSystemDocument, outLineSystemDocument, getSystemDocumentAttachmentList } from '@/api/dictionary'
|
||||
import { userAbandonDoc, getTrialUserTypeList } from '@/api/trials'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
@@ -162,6 +191,7 @@ import TemplateForm from './TemplateForm'
|
||||
|
||||
import attachmentList from './attachmentList'
|
||||
import PreviewFile from '@/components/PreviewFile/index'
|
||||
import attachmentPreview from './attachmentPreview'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
FileTypeId: '',
|
||||
@@ -177,7 +207,7 @@ const searchDataDefault = () => {
|
||||
}
|
||||
export default {
|
||||
name: 'SignatureTemplate',
|
||||
components: { BaseContainer, Pagination, TemplateForm, PreviewFile, attachmentList },
|
||||
components: { BaseContainer, Pagination, TemplateForm, PreviewFile, attachmentList, attachmentPreview },
|
||||
dicts: ['Sys_Document'],
|
||||
props: {
|
||||
isSystem: {
|
||||
@@ -209,7 +239,9 @@ export default {
|
||||
visible: false,
|
||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
||||
width: '800px',
|
||||
}
|
||||
},
|
||||
multipleSelection: [],
|
||||
perview_visible: false
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -217,9 +249,44 @@ export default {
|
||||
this.getUserType()
|
||||
},
|
||||
methods: {
|
||||
openAttachment(row) {
|
||||
handleSelectable(row) {
|
||||
return !row.IsDeleted || !row.IsPublish
|
||||
},
|
||||
handleSelectionChange(val) {
|
||||
this.multipleSelection = val;
|
||||
},
|
||||
// 发布
|
||||
async publishSystemDocument(list) {
|
||||
try {
|
||||
let confirm = await this.$confirm(this.$t('dictionary:signature:confirm:publishFile'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
})
|
||||
if (!confirm) return false
|
||||
let arr = list.filter(item => !item.IsPublish)
|
||||
if (arr.length <= 0) return this.getList()
|
||||
let data = {
|
||||
ids: arr.map(item => item.Id)
|
||||
}
|
||||
this.loading = true
|
||||
let res = await publishSystemDocument(data)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
openAttachment(row, isList = false) {
|
||||
this.SystemDocumentId = row.Id
|
||||
this.config.visible = true
|
||||
this.currentRow = { ...row }
|
||||
if (!isList) {
|
||||
this.perview_visible = true
|
||||
} else {
|
||||
this.config.visible = true
|
||||
}
|
||||
},
|
||||
changeTimeList() {
|
||||
if (this.timeList) {
|
||||
@@ -269,12 +336,23 @@ export default {
|
||||
this.editVisible = true
|
||||
},
|
||||
// 预览
|
||||
handlePreview(row) {
|
||||
async handlePreview(row) {
|
||||
const { Name, FullFilePath } = row
|
||||
this.currentPath = FullFilePath
|
||||
this.currentType = row.Name
|
||||
? Name.substring(Name.lastIndexOf('.') + 1).toLocaleLowerCase()
|
||||
: ''
|
||||
let searchData = {
|
||||
OffLine: false,
|
||||
PageIndex: 1,
|
||||
PageSize: 1000,
|
||||
Asc: false,
|
||||
SortField: null,
|
||||
SystemDocumentId: row.Id
|
||||
}
|
||||
this.currentRow = Object.assign({}, row)
|
||||
let res = await getSystemDocumentAttachmentList(searchData)
|
||||
this.currentRow.AttachmentCount = res.Result.CurrentPageData.length
|
||||
this.previewVisible = true
|
||||
},
|
||||
// 编辑
|
||||
@@ -290,8 +368,13 @@ export default {
|
||||
distinguishCancelAndClose: true,
|
||||
})
|
||||
.then(() => {
|
||||
let arr = row.filter(item => !item.IsDeleted)
|
||||
if (arr.length <= 0) return this.getList()
|
||||
let data = {
|
||||
Ids: arr.map(item => item.Id)
|
||||
}
|
||||
this.loading = true
|
||||
userAbandonDoc(row.Id, true)
|
||||
outLineSystemDocument(data)
|
||||
.then((res) => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
|
||||
@@ -17,12 +17,12 @@
|
||||
<el-form-item :label="$t('system:loginLog:table:LoginUserName')" prop="LoginFaildName">
|
||||
<el-input v-model="searchData.LoginUserName" size="small" clearable style="width: 120px" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('system:loginLog:table:LoginUserType')" prop="LoginUserTypeEnum">
|
||||
<!-- <el-form-item :label="$t('system:loginLog:table:LoginUserType')" prop="LoginUserTypeEnum">
|
||||
<el-select v-model="searchData.LoginUserTypeEnum" clearable style="width: 120px">
|
||||
<el-option v-for="item of $d.UserType" :key="'UserType' + item.label" :value="item.value"
|
||||
:label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<el-form-item :label="$t('system:loginLog:label:IsLoginUncommonly')" prop="IsLoginUncommonly ">
|
||||
<el-select v-model="searchData.IsLoginUncommonly" clearable style="width: 120px">
|
||||
<el-option v-for="item of $d.YesOrNo" :key="item.id" :value="item.value" :label="item.label" />
|
||||
|
||||
@@ -41,7 +41,8 @@
|
||||
<!-- 签署人 -->
|
||||
<el-form-item :label="$t('trials:signRecords:table:user')" v-if="!isDoc">
|
||||
<el-select v-model="searchData.UserId" clearable filterable style="width: 140px">
|
||||
<el-option v-for="item of userOptions" :key="item.UserId" :label="item.RealName" :value="item.UserId">
|
||||
<el-option v-for="item of userOptions" :key="item.ConfirmUserId" :label="item.FullName"
|
||||
:value="item.ConfirmUserId">
|
||||
<span style="float: left">{{ item.RealName || item.FullName }}</span>
|
||||
<span style="
|
||||
float: right;
|
||||
@@ -122,6 +123,13 @@
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column prop="Name" :label="$t('trials:signRecords:table:fileName')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:signRecords:table:AttachmentCount')" prop="AttachmentCount"
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">{{ scope.row.AttachmentCount
|
||||
}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 文件级别 -->
|
||||
<el-table-column prop="IsSystemDoc" :label="$t('trials:signRecords:table:fileLevel')" show-overflow-tooltip
|
||||
width="160" sortable="custom" v-if="!isSystem">
|
||||
@@ -201,10 +209,18 @@
|
||||
<!-- 预览文件 -->
|
||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="$t('trials:signRecords:action:preview')"
|
||||
:fullscreen="true" append-to-body custom-class="base-dialog-wrapper">
|
||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
||||
$t('trials:signRecords:table:AttachmentCount') }} ({{
|
||||
currentRow.AttachmentCount }})</span>
|
||||
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
||||
<PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" @getList="getList" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
||||
:isView="true" @getList="getList" />
|
||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible" :isView="true"
|
||||
v-if="perview_visible" />
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
@@ -216,10 +232,12 @@ import {
|
||||
getSysDocumentConfirmList,
|
||||
getSysDocSignUserList
|
||||
} from '@/api/trials'
|
||||
import { pMTrainingRecordList_Export } from '@/api/export'
|
||||
import { pMTrainingRecordList_Export, getSysDocumentConfirmList_Export } from '@/api/export'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import PreviewFile from '@/components/PreviewFile/index'
|
||||
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
||||
import attachmentList from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentList'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
UserName: null,
|
||||
@@ -240,7 +258,7 @@ const searchDataDefault = () => {
|
||||
}
|
||||
export default {
|
||||
name: 'AttachmentsManagement',
|
||||
components: { BaseContainer, Pagination, PreviewFile },
|
||||
components: { BaseContainer, Pagination, PreviewFile, attachmentPreview, attachmentList },
|
||||
props: {
|
||||
isDoc: {
|
||||
type: Boolean,
|
||||
@@ -276,7 +294,14 @@ export default {
|
||||
trialId: this.$route.query.trialId,
|
||||
exportLoading: false,
|
||||
timeList: [],
|
||||
timeListC: []
|
||||
timeListC: [],
|
||||
SystemDocumentId: null,
|
||||
perview_visible: null,
|
||||
config: {
|
||||
visible: false,
|
||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
||||
width: '800px',
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -285,6 +310,16 @@ export default {
|
||||
this.getUserType()
|
||||
},
|
||||
methods: {
|
||||
openAttachment(row, isList = false) {
|
||||
if (!row.AttachmentCount) return false
|
||||
this.SystemDocumentId = row.Id
|
||||
this.currentRow = { ...row }
|
||||
if (!isList) {
|
||||
this.perview_visible = true
|
||||
} else {
|
||||
this.config.visible = true
|
||||
}
|
||||
},
|
||||
changeTimeList() {
|
||||
if (this.timeList) {
|
||||
this.searchData.StartConfirmTime = this.timeList[0]
|
||||
@@ -305,6 +340,15 @@ export default {
|
||||
},
|
||||
handleExport() {
|
||||
this.exportLoading = true
|
||||
if (this.isSystem) {
|
||||
return getSysDocumentConfirmList_Export(this.searchData)
|
||||
.then(() => {
|
||||
this.exportLoading = false
|
||||
})
|
||||
.catch((err) => {
|
||||
this.exportLoading = false
|
||||
})
|
||||
}
|
||||
pMTrainingRecordList_Export(this.searchData)
|
||||
.then(() => {
|
||||
this.exportLoading = false
|
||||
|
||||
@@ -5,17 +5,9 @@
|
||||
<el-form :inline="true">
|
||||
<!-- 文件类型 -->
|
||||
<el-form-item :label="$t('trials:self-attachment:table:fileType')">
|
||||
<el-select
|
||||
v-model="searchData.FileTypeId"
|
||||
clearable
|
||||
style="width:150px;"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of typeOptions"
|
||||
:key="item.FileTypeId"
|
||||
:label="item.FileType"
|
||||
:value="item.FileTypeId"
|
||||
/>
|
||||
<el-select v-model="searchData.FileTypeId" clearable style="width:150px;">
|
||||
<el-option v-for="item of typeOptions" :key="item.FileTypeId" :label="item.FileType"
|
||||
:value="item.FileTypeId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 文件名称 -->
|
||||
@@ -26,7 +18,7 @@
|
||||
<el-form-item :label="$t('trials:self-attachment:table:isSign')">
|
||||
<el-select v-model="searchData.IsSign" clearable style="width:120px;">
|
||||
<template v-for="item of $d.TrainingStatusEnum">
|
||||
<el-option v-if="item.raw.ValueCN !== '无'" :label="item.label" :value="item.value" :key="item.id"/>
|
||||
<el-option v-if="item.raw.ValueCN !== '无'" :label="item.label" :value="item.value" :key="item.id" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -44,104 +36,71 @@
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<!-- 系统文件列表 -->
|
||||
<el-table
|
||||
ref="TrialAttachments"
|
||||
v-loading="loading"
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table ref="TrialAttachments" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe
|
||||
height="100" @sort-change="handleSortByColumn">
|
||||
<el-table-column type="selection" width="50" />
|
||||
<el-table-column type="index" width="40" />
|
||||
<!-- 文件类型 -->
|
||||
<el-table-column
|
||||
prop="FileType"
|
||||
:label="$t('trials:self-attachment:table:fileType')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column prop="FileType" :label="$t('trials:self-attachment:table:fileType')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column
|
||||
prop="Name"
|
||||
:label="$t('trials:self-attachment:table:fileName')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column prop="Name" :label="$t('trials:self-attachment:table:fileName')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:self-attachment:table:AttachmentCount')" prop="AttachmentCount"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">{{ scope.row.AttachmentCount
|
||||
}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否废除 -->
|
||||
<el-table-column
|
||||
prop="IsDeleted"
|
||||
:label="$t('trials:self-attachment:table:isDeleted')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<el-table-column prop="IsDeleted" :label="$t('trials:self-attachment:table:isDeleted')" show-overflow-tooltip
|
||||
sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{ $fd('TrainingStatus', scope.row.IsDeleted) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('TrainingStatus', scope.row.IsDeleted) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 上传时间 -->
|
||||
<el-table-column
|
||||
prop="CreateTime"
|
||||
:label="$t('trials:self-attachment:table:uploadTime')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column prop="CreateTime" :label="$t('trials:self-attachment:table:uploadTime')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<!-- 是否签署 -->
|
||||
<el-table-column
|
||||
prop="ConfirmTime"
|
||||
:label="$t('trials:self-attachment:table:isSign')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<el-table-column prop="ConfirmTime" :label="$t('trials:self-attachment:table:isSign')" show-overflow-tooltip
|
||||
sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed) }}</el-tag>
|
||||
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed)
|
||||
}}</el-tag>
|
||||
<el-tag v-else type="danger">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 签署时间 -->
|
||||
<el-table-column
|
||||
prop="ConfirmTime"
|
||||
:label="$t('trials:self-attachment:table:signTime')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column prop="ConfirmTime" :label="$t('trials:self-attachment:table:signTime')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
|
||||
<el-table-column :label="$t('common:action:action')">
|
||||
<template slot-scope="scope">
|
||||
<!-- 预览 -->
|
||||
<el-button
|
||||
icon="el-icon-view"
|
||||
circle
|
||||
:title="$t('trials:self-attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)"
|
||||
/>
|
||||
<el-button icon="el-icon-view" circle :title="$t('trials:self-attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)" />
|
||||
<!-- 签署 -->
|
||||
<el-button
|
||||
icon="el-icon-edit-outline"
|
||||
circle
|
||||
:disabled="!!scope.row.ConfirmTime"
|
||||
:title="$t('trials:self-attachment:action:sign')"
|
||||
@click="handleSign(scope.row)"
|
||||
/>
|
||||
<el-button icon="el-icon-edit-outline" circle :disabled="!!scope.row.ConfirmTime"
|
||||
:title="$t('trials:self-attachment:action:sign')" @click="handleSign(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||
@pagination="getList" />
|
||||
</template>
|
||||
|
||||
<!-- 预览文件 -->
|
||||
<el-dialog
|
||||
v-if="previewVisible"
|
||||
:visible.sync="previewVisible"
|
||||
:title="title"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="title" :fullscreen="true" append-to-body
|
||||
custom-class="base-dialog-wrapper">
|
||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
||||
$t('trials:self-attachment:table:AttachmentCount') }} ({{
|
||||
currentRow.AttachmentCount }})</span>
|
||||
<span v-if="!currentIsConfirm" style="position: fixed;right: 75px;top: 14px;">
|
||||
<span style="color:red;margin-right:10px;">
|
||||
<!-- 请仔细阅读文件,并签名确认 -->
|
||||
@@ -149,13 +108,8 @@
|
||||
<span v-show="duration < currentMinMinutes * 60">{{ `(${currentMinMinutes * 60 - duration}s)` }}</span>
|
||||
</span>
|
||||
<!-- 签署 -->
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="timer !== null || duration === 0"
|
||||
:loading="btnLoading"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="timer !== null || duration === 0" :loading="btnLoading"
|
||||
@click="handleConfirm">
|
||||
{{ $t('common:button:sign') }}
|
||||
<!-- {{ duration >= currentMinMinutes * 60?'确认':`确认(${currentMinMinutes * 60 - duration}s)` }} -->
|
||||
</el-button>
|
||||
@@ -167,19 +121,19 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 签名弹框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
append-to-body
|
||||
>
|
||||
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
|
||||
append-to-body>
|
||||
<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>
|
||||
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${currentUser})` }}</span>
|
||||
</div>
|
||||
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName" :trial-id="trialId" @closeDialog="closeSignDialog" />
|
||||
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName"
|
||||
:trial-id="trialId" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
||||
:isView="true" @getList="getList" />
|
||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible" :isView="true"
|
||||
v-if="perview_visible" />
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
@@ -189,6 +143,8 @@ import Pagination from '@/components/Pagination'
|
||||
import PreviewFile from '@/components/PreviewFile/index'
|
||||
import SignForm from './components/SignForm'
|
||||
import store from '@/store'
|
||||
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
||||
import attachmentList from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentList'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
FileTypeId: '',
|
||||
@@ -202,7 +158,7 @@ const searchDataDefault = () => {
|
||||
}
|
||||
export default {
|
||||
name: 'TrialAttachments',
|
||||
components: { BaseContainer, Pagination, PreviewFile, SignForm },
|
||||
components: { BaseContainer, Pagination, PreviewFile, SignForm, attachmentPreview, attachmentList },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
@@ -223,7 +179,14 @@ export default {
|
||||
fileName: '',
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
typeOptions: [],
|
||||
trialId: this.$route.query.trialId
|
||||
trialId: this.$route.query.trialId,
|
||||
SystemDocumentId: null,
|
||||
perview_visible: null,
|
||||
config: {
|
||||
visible: false,
|
||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
||||
width: '800px',
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -240,6 +203,16 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openAttachment(row, isList = false) {
|
||||
if (!row.AttachmentCount) return false
|
||||
this.SystemDocumentId = row.Id
|
||||
this.currentRow = { ...row }
|
||||
if (!isList) {
|
||||
this.perview_visible = true
|
||||
} else {
|
||||
this.config.visible = true
|
||||
}
|
||||
},
|
||||
// 获取系统文件数据
|
||||
getList() {
|
||||
this.loading = true
|
||||
@@ -336,8 +309,8 @@ export default {
|
||||
// 文档签署已完成,是否关闭弹窗?
|
||||
this.$confirm(this.$t('trials:self-attachment:message:closeDocument')).then(() => {
|
||||
this.previewVisible = false
|
||||
}).catch(()=>{})
|
||||
|
||||
}).catch(() => { })
|
||||
|
||||
} else {
|
||||
this.handleSign(res.Result)
|
||||
}
|
||||
|
||||
@@ -729,7 +729,7 @@ export default {
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||
@@ -766,7 +766,7 @@ export default {
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||
@@ -801,7 +801,7 @@ export default {
|
||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||
this.trialId
|
||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||
|
||||
@@ -1406,7 +1406,7 @@ export default {
|
||||
)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (row.ReadingTool === 0) {
|
||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${row.TrialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${row.TrialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -263,7 +263,7 @@ export default {
|
||||
series: '',
|
||||
ToolStateManager: null,
|
||||
renderedMeasured: [],
|
||||
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate', 'RectangleRoi'],
|
||||
measuredTools: ['Length', 'Bidirectional', 'ArrowAnnotate', 'RectangleRoi', 'Probe'],
|
||||
measureData: [],
|
||||
selectedLesion: null,
|
||||
activeTool: 0, // 0:enable 1:passive 2:active
|
||||
@@ -303,8 +303,8 @@ export default {
|
||||
|
||||
],
|
||||
scrollSyncInfo: { offset: 0 },
|
||||
hideMeasureArr: []
|
||||
|
||||
hideMeasureArr: [],
|
||||
isInitWwwc: true
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -565,7 +565,6 @@ export default {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
} else if (this.activeToolName === 'Length' || this.activeToolName === 'Bidirectional' && this.readingTaskState < 2) {
|
||||
console.log(e.detail.image)
|
||||
if (!e.detail.image.columnPixelSpacing || !e.detail.image.rowPixelSpacing) {
|
||||
// '该影像不具备测量长度所需的必要数据,不能进行长度测量。请选择其他工具进行标注。'
|
||||
this.$confirm(this.$t('trials:reading:warnning:msg56'), '', {
|
||||
@@ -578,6 +577,13 @@ export default {
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
} else if (this.CriterionType === 21 && this.activeToolName === 'Probe' && this.readingTaskState < 2) {
|
||||
if (!(e.detail.image.imageFrame.photometricInterpretation === 'MONOCHROME1' || e.detail.image.imageFrame.photometricInterpretation === 'MONOCHROME2')) {
|
||||
this.$alert(this.$t('trials:MRIPDFF:message:message5'))
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
},
|
||||
pointNearTool(e) {
|
||||
@@ -607,7 +613,11 @@ export default {
|
||||
if ((i.LesionType === 0 || i.LesionType === 1 || i.LesionType === 7) && i.IsFirstChangeTask) {
|
||||
arr.push(i.OrderMarkName)
|
||||
}
|
||||
if (i.Id && this.readingTaskState >= 2) {
|
||||
arr.push(i.OrderMarkName)
|
||||
}
|
||||
})
|
||||
console.log(arr)
|
||||
return arr
|
||||
},
|
||||
getMergeMarks(measureDatas) {
|
||||
@@ -616,6 +626,9 @@ export default {
|
||||
if ((i.LesionType === 0) && i.SplitOrMergeType === 1) {
|
||||
arr.push(i.OrderMarkName)
|
||||
}
|
||||
if (i.Id && this.readingTaskState >= 2) {
|
||||
arr.push(i.OrderMarkName)
|
||||
}
|
||||
})
|
||||
return arr
|
||||
},
|
||||
@@ -661,7 +674,7 @@ export default {
|
||||
},
|
||||
sliderMousemove(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
console.log('sliderMousemove')
|
||||
// console.log('sliderMousemove')
|
||||
var PX = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
|
||||
var boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
if (PX < 0) return
|
||||
@@ -692,7 +705,7 @@ export default {
|
||||
} else if (criterionType === 2) {
|
||||
this.disabledMarks = this.getMergeMarks(this.visitTaskList[idx].MeasureData)
|
||||
} else {
|
||||
this.disabledMarks = []
|
||||
this.disabledMarks = this.getDisabledMarks(this.visitTaskList[idx].MeasureData)
|
||||
}
|
||||
return true
|
||||
},
|
||||
@@ -785,6 +798,8 @@ export default {
|
||||
} else if (toolType === 'Length') {
|
||||
// toolState.data[i].length = this.calculateLenth(toolState.data[i])
|
||||
}
|
||||
measureData.largestPixelValue = image.imageFrame.largestPixelValue
|
||||
measureData.imageId = imageId
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
@@ -901,6 +916,9 @@ export default {
|
||||
}
|
||||
} else if (this.activeTool === 1 && this.readingTaskState < 2) {
|
||||
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
|
||||
} else if (this.readingTaskState >= 2 && this.isCurrentTask) {
|
||||
// setToolPassiveForElement
|
||||
cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
|
||||
} else {
|
||||
cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
|
||||
}
|
||||
@@ -919,6 +937,9 @@ export default {
|
||||
}
|
||||
}
|
||||
})
|
||||
if (this.readingTaskState >= 2 && this.activeToolName && this.isCurrentTask) {
|
||||
cornerstoneTools.setToolActiveForElement(element, this.activeToolName, { mouseButtonMask: 1 })
|
||||
}
|
||||
},
|
||||
setMeasureDataVisible() {
|
||||
if (this.readingTaskState >= 2) return
|
||||
@@ -986,6 +1007,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mouseClick(e) {
|
||||
if (this.readingTaskState >= 2) return
|
||||
const { element, currentPoints, image, viewport } = e.detail
|
||||
var imageId = image.imageId
|
||||
const imageInfo = this.getInstanceInfo(imageId)
|
||||
@@ -1010,6 +1032,8 @@ export default {
|
||||
var questionInfo = this.measureData[idx]
|
||||
// const canvas = this.canvas.querySelector('canvas')
|
||||
// measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
|
||||
measureData.largestPixelValue = image.imageFrame.largestPixelValue
|
||||
measureData.imageId = imageId
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
@@ -1035,6 +1059,7 @@ export default {
|
||||
},
|
||||
loadImageStack(dicomSeries) {
|
||||
return new Promise(resolve => {
|
||||
this.isInitWwwc = true
|
||||
this.isCurrentTask = dicomSeries.isCurrentTask
|
||||
this.isBaseline = dicomSeries.isBaseLineTask
|
||||
this.readingTaskState = dicomSeries.readingTaskState
|
||||
@@ -1073,7 +1098,8 @@ export default {
|
||||
} else if (criterionType === 2) {
|
||||
this.disabledMarks = this.getMergeMarks(this.visitTaskList[idx].MeasureData)
|
||||
} else {
|
||||
this.disabledMarks = []
|
||||
// this.disabledMarks = []
|
||||
this.disabledMarks = this.getDisabledMarks(this.visitTaskList[idx].MeasureData)
|
||||
}
|
||||
|
||||
this.maxVistNum = this.visitTaskList[this.visitTaskList.length - 1].VisitTaskNum
|
||||
@@ -1202,7 +1228,7 @@ export default {
|
||||
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
|
||||
this.stack.instanceId = instanceId
|
||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
||||
// this.resetWwwc()
|
||||
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
@@ -1300,6 +1326,9 @@ export default {
|
||||
this.scrollSyncInfo.offset = 0
|
||||
}
|
||||
this.renderMeasuredData(e)
|
||||
if (this.isInitWwwc) {
|
||||
this.resetWwwc()
|
||||
}
|
||||
},
|
||||
getOrientationMarker(element) {
|
||||
const enabledElement = cornerstone.getEnabledElement(element)
|
||||
@@ -1336,6 +1365,8 @@ export default {
|
||||
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
|
||||
if (e.detail.toolName === 'Length' || e.detail.toolName === 'ArrowAnnotate' || e.detail.toolName === 'RectangleRoi') {
|
||||
const measureData = {}
|
||||
measureData.largestPixelValue = element.image.imageFrame.largestPixelValue
|
||||
measureData.imageId = imageId
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
@@ -1353,6 +1384,8 @@ export default {
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
|
||||
} else if (e.detail.toolName === 'Bidirectional') {
|
||||
const measureData = {}
|
||||
measureData.largestPixelValue = element.image.imageFrame.largestPixelValue
|
||||
measureData.imageId = imageId
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
@@ -1369,6 +1402,8 @@ export default {
|
||||
cornerstoneTools.setToolPassiveForElement(this.canvas, e.detail.toolName)
|
||||
} else if (e.detail.toolName === 'Probe') {
|
||||
const measureData = {}
|
||||
measureData.largestPixelValue = element.image.imageFrame.largestPixelValue
|
||||
measureData.imageId = imageId
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
@@ -1478,6 +1513,8 @@ export default {
|
||||
var questionInfo = this.measureData[idx]
|
||||
// const canvas = this.canvas.querySelector('canvas')
|
||||
// measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
|
||||
measureData.largestPixelValue = element.image.imageFrame.largestPixelValue
|
||||
measureData.imageId = imageId
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
@@ -1669,6 +1706,8 @@ export default {
|
||||
},
|
||||
|
||||
resetWwwc() {
|
||||
// console.log('resetWwwc')
|
||||
this.isInitWwwc = true
|
||||
this.toolState.viewportInvert = false
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
// viewport.invert = false
|
||||
@@ -1679,7 +1718,7 @@ export default {
|
||||
},
|
||||
|
||||
setWwwc(ww, wc) {
|
||||
// console.log('setWwwc', ww, wc)
|
||||
this.isInitWwwc = false
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.voi.windowWidth = ww
|
||||
viewport.voi.windowCenter = wc
|
||||
|
||||
@@ -416,7 +416,7 @@
|
||||
<dicom-canvas
|
||||
v-if="canvasW"
|
||||
:ref="`dicomCanvas${i-1}`"
|
||||
:style="{width:canvasW,height: canvasH}"
|
||||
:style="{width: fullScreenIndex === i-1 ? fullScreenWidth : canvasW,height: fullScreenIndex === i-1 ? fullScreenHeight : canvasH}"
|
||||
:canvas-index="i-1"
|
||||
:is-active="i-1===currentDicomCanvasIndex"
|
||||
:is-scroll-sync="isScrollSync"
|
||||
@@ -989,7 +989,10 @@ export default {
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
tmpData: null
|
||||
tmpData: null,
|
||||
fullScreenIndex: -1,
|
||||
fullScreenWidth: window.innerWidth - 570 + 'px',
|
||||
fullScreenHeight: window.innerHeight - 130 + 'px'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1379,22 +1382,25 @@ export default {
|
||||
this.personalConfigDialog.visible = true
|
||||
},
|
||||
setCornerstoneStyle(i) {
|
||||
if (this.layoutCol === 1 && this.layoutRow === 1) {
|
||||
this.fullScreenIndex = -1
|
||||
return
|
||||
}
|
||||
if (this.cornerstoneStyle.position) {
|
||||
this.cornerstoneStyle = {}
|
||||
this.setCanvasStyle()
|
||||
this.fullScreenIndex = -1
|
||||
} else {
|
||||
this.cornerstoneStyle = {
|
||||
position: 'absolute',
|
||||
top: '72px',
|
||||
top: '67px',
|
||||
left: '0px',
|
||||
right: '350px',
|
||||
zIndex: 10
|
||||
zIndex: 10,
|
||||
}
|
||||
this.canvasW = window.innerWidth - 570 + 'px'
|
||||
this.canvasH = window.innerHeight - 130 + 'px'
|
||||
this.fullScreenIndex = this.currentDicomCanvasIndex
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
// this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].reloadCanvas()
|
||||
for (var i = 0; i < this.maxCanvas; i++) {
|
||||
this.$refs[`dicomCanvas${i}`][0].reloadCanvas()
|
||||
}
|
||||
@@ -1941,6 +1947,7 @@ export default {
|
||||
},
|
||||
// 切换布局
|
||||
changeLayout(name) {
|
||||
this.fullScreenIndex = -1
|
||||
if (this.activeTool) {
|
||||
if (this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].isCurrentTask && this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].readingTaskState < 2) {
|
||||
this.$nextTick(() => {
|
||||
@@ -2043,14 +2050,17 @@ export default {
|
||||
if (i === -1) return
|
||||
var isCurrentTask = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].isCurrentTask
|
||||
var readingTaskState = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].readingTaskState
|
||||
if (!isCurrentTask || readingTaskState >= 2) {
|
||||
if (!isCurrentTask) {
|
||||
this.measuredTools[i].isDisabled = true
|
||||
e.target.style.cursor = 'not-allowed'
|
||||
if (this.activeTool) {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolEnabled(toolName)
|
||||
this.activeTool = ''
|
||||
}
|
||||
} else {
|
||||
} else if (isCurrentTask && readingTaskState >= 2) {
|
||||
this.measuredTools[i].isDisabled = false
|
||||
e.target.style.cursor = 'pointer'
|
||||
} else if (isCurrentTask && readingTaskState < 2) {
|
||||
// var obj = this.$refs['measurementList'].isCanActiveTool(toolName, true)
|
||||
var obj = this.$refs['measurementList'].isCanActiveTool(toolName, true)
|
||||
this.measuredTools[i].disabledReason = obj.reason
|
||||
@@ -2087,7 +2097,7 @@ export default {
|
||||
var toolObj = this.measuredTools.find(i => i.toolName === toolName)
|
||||
if (!toolObj || toolObj.isDisabled) return
|
||||
var dicomSeries = this.canvasObj[this.currentDicomCanvasIndex]
|
||||
if (dicomSeries.isCurrentTask && isMeasuredTool && dicomSeries.readingTaskState < 2) {
|
||||
if (dicomSeries.isCurrentTask && isMeasuredTool) {
|
||||
if (this.activeTool) {
|
||||
this.measuredTools.forEach(item => {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setToolPassive(item.toolName)
|
||||
@@ -2248,13 +2258,14 @@ export default {
|
||||
this.customWwc.visible = false
|
||||
},
|
||||
toggleInvert() {
|
||||
if (this.activeTool === 'reversecolor') {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetWwwc()
|
||||
this.activeTool = ''
|
||||
} else {
|
||||
this.activeTool = 'reversecolor'
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
|
||||
}
|
||||
// if (this.activeTool === 'reversecolor') {
|
||||
// this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetWwwc()
|
||||
// this.activeTool = ''
|
||||
// } else {
|
||||
// this.activeTool = 'reversecolor'
|
||||
// this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
|
||||
// }
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
|
||||
},
|
||||
setImageIndexSync() {
|
||||
this.isScrollSync = !this.isScrollSync
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -203,7 +203,6 @@ export default {
|
||||
console.log(toolsUtilities)
|
||||
this.subjectCode = this.$route.query.subjectCode
|
||||
var element = document.getElementById(`viewport${this.index}`)
|
||||
|
||||
element.addEventListener(VOLUME_NEW_IMAGE, this.handleVolumeNewImage)
|
||||
element.addEventListener(Enums.Events.CAMERA_MODIFIED, this.handleCameraModified)
|
||||
element.addEventListener(Enums.Events.VOI_MODIFIED, this.handleVOIModified)
|
||||
@@ -249,8 +248,10 @@ export default {
|
||||
this.getOrientationMarker()
|
||||
this.sliderBoxHeight = imageIndex * 100 / (this.seriesInfo.imageMaxLength - 1)
|
||||
}
|
||||
|
||||
var properties = viewport.getProperties()
|
||||
let properties = viewport.getProperties()
|
||||
if (this.index === 3) {
|
||||
properties = viewport.getProperties(`cornerstoneStreamingImageVolume:PT_VOLUME_ID`)
|
||||
}
|
||||
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
@@ -324,7 +325,12 @@ export default {
|
||||
viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (!viewport) return
|
||||
|
||||
var properties = viewport.getProperties()
|
||||
let properties = viewport.getProperties()
|
||||
if (this.index === 3) {
|
||||
// const volumeId = viewport.getVolumeId()
|
||||
const volumeId = `cornerstoneStreamingImageVolume:PT_VOLUME_ID`
|
||||
properties = viewport.getProperties(volumeId)
|
||||
}
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
||||
@@ -562,12 +568,21 @@ export default {
|
||||
ctx.fillRect(0, 0, rectWidth, rectHeight)
|
||||
},
|
||||
setWwWc() {
|
||||
var properties = viewport.getProperties()
|
||||
let properties = viewport.getProperties()
|
||||
if (this.index === 3) {
|
||||
properties = viewport.getProperties(`cornerstoneStreamingImageVolume:PT_VOLUME_ID`)
|
||||
}
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const windowWidth = upper - lower
|
||||
const windowCenter = (upper + lower) / 2
|
||||
// console.log(lower, upper)
|
||||
// const windowWidth = upper - lower
|
||||
// const windowCenter = (upper + lower) / 2
|
||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
)
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
this.$emit('upperRangeChange', Math.round(windowWidth))
|
||||
}
|
||||
},
|
||||
async getScreenshots() {
|
||||
|
||||
+10
-3
@@ -4,7 +4,8 @@ import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunc
|
||||
import { utilities } from '@cornerstonejs/core'
|
||||
const { getColormap } = utilities.colormap
|
||||
function setPetColorMapTransferFunctionForVolumeActor(
|
||||
volumeInfo
|
||||
volumeInfo,
|
||||
isPT = false
|
||||
) {
|
||||
const { volumeActor, preset } = volumeInfo
|
||||
const mapper = volumeActor.getMapper()
|
||||
@@ -22,8 +23,14 @@ function setPetColorMapTransferFunctionForVolumeActor(
|
||||
|
||||
// Create scalar opacity function
|
||||
const ofun = vtkPiecewiseFunction.newInstance()
|
||||
ofun.addPoint(0, 0.0)
|
||||
ofun.addPoint(0.1, 0.9)
|
||||
if (isPT) {
|
||||
ofun.addPoint(0, 0.0)
|
||||
ofun.addPoint(0.1, 1.0)
|
||||
} else {
|
||||
ofun.addPoint(0, 0.0)
|
||||
ofun.addPoint(0.1, 0.9)
|
||||
}
|
||||
|
||||
ofun.addPoint(5, 1.0)
|
||||
|
||||
volumeActor.getProperty().setScalarOpacity(0, ofun)
|
||||
|
||||
@@ -205,6 +205,7 @@
|
||||
import { saveTableQuestionMark, submitTaskRowInfo, deleteTableQuestionMark, deleteSingleTableQuestionMark } from '@/api/reading'
|
||||
import DicomEvent from './../DicomEvent'
|
||||
import store from '@/store'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
export default {
|
||||
name: 'MeasurementForm',
|
||||
props: {
|
||||
@@ -444,7 +445,12 @@ export default {
|
||||
// 维护标记信息
|
||||
measureData.data.remark = this.getLesionName(this.orderMark, this.activeQuestionMark)
|
||||
}
|
||||
const val = measureData.data.cachedStats.mean / 10
|
||||
// const val = measureData.data.cachedStats.mean / 10
|
||||
let val = parseFloat(measureData.data.cachedStats.mean)
|
||||
// let imagePixelModule = cornerstone.metaData.get('imagePixelModule', measureData.imageId)
|
||||
if (measureData.largestPixelValue >= 500) {
|
||||
val = val / 10
|
||||
}
|
||||
this.$set(this.questionForm, measureData.tableQuestionId, val.toFixed(this.digitPlaces))
|
||||
data = {
|
||||
Id: '',
|
||||
@@ -574,14 +580,26 @@ export default {
|
||||
let params = {}
|
||||
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
|
||||
const measureData = this.markList[i].measureData.MeasureData
|
||||
const tableQuestionId = this.markList[i].tableQuestionId
|
||||
if (this.questionForm[tableQuestionId] > 100) {
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:MRIPDFF:message:message4'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
}
|
||||
// 上传截图
|
||||
|
||||
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: measureData.OrderMarkName, lesionType: null, isMarked: !!measureData }, async val => {
|
||||
params = Object.assign({}, this.markList[i].measureData)
|
||||
if (val) {
|
||||
const pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
|
||||
params.PicturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
|
||||
}
|
||||
const tableQuestionId = this.markList[i].tableQuestionId
|
||||
|
||||
params.Answer = this.questionForm[tableQuestionId]
|
||||
params.MeasureData = JSON.stringify(this.markList[i].measureData.MeasureData)
|
||||
loading.close()
|
||||
|
||||
@@ -264,7 +264,6 @@ export default {
|
||||
if (item.Type === 'table' && item.Id === obj.questionId) {
|
||||
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
|
||||
item.TableQuestions.Answers[idx].isMeasurable = obj.isMeasurable
|
||||
console.log(obj.isMeasurable)
|
||||
item.TableQuestions.Answers[idx].mean = obj.mean
|
||||
item.TableQuestions.Answers[idx].saveTypeEnum = obj.saveTypeEnum
|
||||
|
||||
|
||||
@@ -556,7 +556,7 @@
|
||||
<dicom-canvas
|
||||
v-if="canvasW"
|
||||
:ref="`dicomCanvas${i - 1}`"
|
||||
:style="{ width: canvasW, height: canvasH }"
|
||||
:style="{width: fullScreenIndex === i-1 ? fullScreenWidth : canvasW,height: fullScreenIndex === i-1 ? fullScreenHeight : canvasH}"
|
||||
:canvas-index="i - 1"
|
||||
:is-active="i - 1 === currentDicomCanvasIndex"
|
||||
:is-scroll-sync="isScrollSync"
|
||||
@@ -895,6 +895,9 @@ export default {
|
||||
uploadTrialCriterion: {},
|
||||
uploadStatus: 'upload',
|
||||
taskId: '',
|
||||
fullScreenIndex: -1,
|
||||
fullScreenWidth: window.innerWidth - 570 + 'px',
|
||||
fullScreenHeight: window.innerHeight - 128 + 'px'
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1314,22 +1317,25 @@ export default {
|
||||
this.personalConfigDialog.visible = true
|
||||
},
|
||||
setCornerstoneStyle(i) {
|
||||
if (this.layoutCol === 1 && this.layoutRow === 1) {
|
||||
this.fullScreenIndex = -1
|
||||
return
|
||||
}
|
||||
if (this.cornerstoneStyle.position) {
|
||||
this.cornerstoneStyle = {}
|
||||
this.setCanvasStyle()
|
||||
this.fullScreenIndex = -1
|
||||
} else {
|
||||
this.cornerstoneStyle = {
|
||||
position: 'absolute',
|
||||
top: '72px',
|
||||
top: '70px',
|
||||
left: '205px',
|
||||
right: '350px',
|
||||
zIndex: 10,
|
||||
}
|
||||
this.canvasW = window.innerWidth - 570 + 'px'
|
||||
this.canvasH = window.innerHeight - 130 + 'px'
|
||||
this.fullScreenIndex = this.currentDicomCanvasIndex
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
// this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].reloadCanvas()
|
||||
for (var i = 0; i < this.maxCanvas; i++) {
|
||||
this.$refs[`dicomCanvas${i}`][0].reloadCanvas()
|
||||
}
|
||||
@@ -1928,6 +1934,7 @@ export default {
|
||||
},
|
||||
// 切换布局
|
||||
changeLayout(name) {
|
||||
this.fullScreenIndex = -1
|
||||
if (this.activeTool) {
|
||||
if (
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0]
|
||||
@@ -2301,15 +2308,16 @@ export default {
|
||||
this.customWwc.visible = false
|
||||
},
|
||||
toggleInvert() {
|
||||
if (this.activeTool === 'reversecolor') {
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetWwwc()
|
||||
this.activeTool = ''
|
||||
} else {
|
||||
this.activeTool = 'reversecolor'
|
||||
this.$refs[
|
||||
`dicomCanvas${this.currentDicomCanvasIndex}`
|
||||
][0].toggleInvert()
|
||||
}
|
||||
// if (this.activeTool === 'reversecolor') {
|
||||
// this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].resetWwwc()
|
||||
// this.activeTool = ''
|
||||
// } else {
|
||||
// this.activeTool = 'reversecolor'
|
||||
// this.$refs[
|
||||
// `dicomCanvas${this.currentDicomCanvasIndex}`
|
||||
// ][0].toggleInvert()
|
||||
// }
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].toggleInvert()
|
||||
},
|
||||
setImageIndexSync() {
|
||||
this.isScrollSync = !this.isScrollSync
|
||||
|
||||
+1
-1
@@ -456,7 +456,7 @@ export default {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v, oldv) {
|
||||
console.log(v)
|
||||
// console.log(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<template>
|
||||
<div ref="container" style="width:100%;height:100%" class="dicom-container">
|
||||
<!-- 访视阅片 -->
|
||||
<div v-if="readingCategory=== 1 && (CriterionType === 7)" class="reading-wrapper">
|
||||
<VisitReview />
|
||||
<div v-if="readingCategory=== 1 && (CriterionType === 7 || ((CriterionType === 1 || CriterionType === 0) && readingVersionEnum === 1)) " class="reading-wrapper">
|
||||
<VisitReview :reading-tool="readingTool" />
|
||||
</div>
|
||||
<div v-else-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType !== 0" class="reading-wrapper">
|
||||
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeave">
|
||||
@@ -222,7 +222,7 @@ export default {
|
||||
isReadingTaskViewInOrder: null,
|
||||
firstTaskReadingCategory: null,
|
||||
criterionType: null,
|
||||
readingTool: null,
|
||||
readingTool: 0,
|
||||
dialogVisible: false,
|
||||
TrialReadingCriterionId: null,
|
||||
isNewSubject: null,
|
||||
@@ -234,7 +234,8 @@ export default {
|
||||
isFullscreen: false,
|
||||
tipVisible: false,
|
||||
closeCDVisible: false,
|
||||
cdVisitTaskId: ''
|
||||
cdVisitTaskId: '',
|
||||
readingVersionEnum: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -271,7 +272,7 @@ export default {
|
||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
||||
// this.isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
// this.criterionType = this.$router.currentRoute.query.criterionType
|
||||
// this.readingTool = this.$router.currentRoute.query.readingTool
|
||||
this.readingTool = this.$router.currentRoute.query.readingTool ? Number(this.$router.currentRoute.query.readingTool) : 0
|
||||
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
// this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
||||
|
||||
@@ -346,6 +347,7 @@ export default {
|
||||
localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback)
|
||||
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
||||
this.readingCategory = res.Result.ReadingCategory
|
||||
this.readingVersionEnum = res.Result.ReadingVersionEnum
|
||||
this.questionFormChangeState = false
|
||||
this.questionFormChangeNum = 0
|
||||
if (this.isExistsClinicalData && this.isNeedReadClinicalData && !this.isReadClinicalData) {
|
||||
@@ -594,6 +596,10 @@ export default {
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
::v-deep .el-radio__input.is-disabled.is-checked .el-radio__inner {
|
||||
background-color: #428bca;
|
||||
border-color: #428bca;
|
||||
}
|
||||
|
||||
.full-dialog-container{
|
||||
::v-deep.is-fullscreen .el-dialog__body{
|
||||
|
||||
@@ -0,0 +1,276 @@
|
||||
<template>
|
||||
<el-form ref="fusionForm" :model="fusionForm" label-width="120px" label-position="left">
|
||||
<!-- 任务名称 -->
|
||||
<el-form-item :label="$t('trials:lugano:fusionDialog:label:taskBlindName')" prop="taskBlindName">
|
||||
<el-select v-model="fusionForm.visitTaskId" clearable @change="handleTaskIdChange" disabled>
|
||||
<el-option v-for="item in taskList" :key="item.VisitTaskId" :label="item.TaskBlindName"
|
||||
:value="item.VisitTaskId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 检查 -->
|
||||
<el-form-item :label="$t('trials:lugano:fusionDialog:label:study')" prop="studyId" :rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:select'), trigger: 'blur' }
|
||||
]">
|
||||
<el-select v-model="fusionForm.studyId" clearable @change="handleStudyIdChange">
|
||||
<el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode" :value="item.StudyId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 融合图像 -->
|
||||
<label style="color: #dfdfdf;line-height: 36px;vertical-align: middle;font-size: 14px;">{{
|
||||
$t('trials:lugano:fusionDialog:label:fusionImages') }}</label>
|
||||
<div style="display: flex;flex-direction: row;justify-content: space-between;margin-bottom:10px;"
|
||||
class="series-table">
|
||||
|
||||
<div style="border: 1px solid #5e5e5e;border-radius: 5px;padding: 0 10px;">
|
||||
<!-- CT/MRI序列 -->
|
||||
<h3 style="color:#ddd">{{ $t('trials:lugano:fusionDialog:label:ctSeries') }}</h3>
|
||||
<el-table ref="ctSeries" :data="ctSeries" :show-header="false" style="width: 380px" size="mini" height="300"
|
||||
:default-sort="{ prop: 'instanceCount', order: 'descending' }" @selection-change="handleCTSelectionChange"
|
||||
@select="handleCTSelect">
|
||||
|
||||
<el-table-column type="selection" width="30" />
|
||||
<el-table-column label="" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-image style="width: 60px; height: 60px"
|
||||
:src="`${OSSclientConfig.basePath}${scope.row.ImageResizePath}`" fit="fit" crossorigin="anonymous" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="" min-width="50" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<div>#{{ scope.row.SeriesNumber }} </div>
|
||||
<div>{{ scope.row.Modality }}: {{ scope.row.InstanceCount }} images T: {{
|
||||
parseFloat(scope.row.SliceThickness).toFixed(digitPlaces) }}</div>
|
||||
<div>{{ scope.row.Description }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</div>
|
||||
|
||||
<div style="border: 1px solid #5e5e5e;border-radius: 5px;padding: 0 10px;">
|
||||
<!-- PET序列 -->
|
||||
<h3 style="color:#ddd">{{ $t('trials:lugano:fusionDialog:label:ptSeries') }}</h3>
|
||||
<el-table ref="petSeries" :data="petSeries" :show-header="false" style="width: 380px" size="mini" height="300"
|
||||
@selection-change="handlePTSelectionChange" @select="handlePTSelect">
|
||||
<el-table-column type="selection" width="30" />
|
||||
<el-table-column label="" width="100">
|
||||
<template slot-scope="scope">
|
||||
<el-image style="width: 60px; height: 60px"
|
||||
:src="`${OSSclientConfig.basePath}${scope.row.ImageResizePath}`" fit="fit" crossorigin="anonymous" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="" min-width="50" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<div>#{{ scope.row.SeriesNumber }} </div>
|
||||
<div>{{ scope.row.Modality }}: {{ scope.row.InstanceCount }} images T: {{
|
||||
parseFloat(scope.row.SliceThickness).toFixed(digitPlaces) }}</div>
|
||||
<div>{{ scope.row.Description }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item style="text-align:right;">
|
||||
<!-- 取消 -->
|
||||
<el-button size="mini" @click="handleCancel">{{ $t('common:button:cancel') }}</el-button>
|
||||
<!-- 确认 -->
|
||||
<el-button type="primary" size="mini" @click="handleSubmitFusionSeries">
|
||||
{{ $t('common:button:confirm') }}</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'FusionForm',
|
||||
props: {
|
||||
taskList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
}
|
||||
},
|
||||
activeTaskIndex: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fusionForm: {
|
||||
visitTaskId: '',
|
||||
studyId: '',
|
||||
taskBlindName: '',
|
||||
isBaseLineTask: null,
|
||||
ctSeriesInfo: {},
|
||||
petSeriesInfo: {},
|
||||
defaultStudyId: '',
|
||||
defaultCTSeriesId: '',
|
||||
defaultPTSeriesId: ''
|
||||
},
|
||||
studyList: [],
|
||||
ctSeries: [],
|
||||
petSeries: [],
|
||||
petctWindow: null,
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
initForm() {
|
||||
if (this.taskList.length === 0) return
|
||||
this.getStudyList(this.taskList[this.activeTaskIndex])
|
||||
this.handleStudyIdChange(this.studyList[0].StudyId)
|
||||
if (this.studyList.length > 0) {
|
||||
this.fusionForm.studyId = this.studyList[0].StudyId
|
||||
this.handleStudyIdChange(this.studyList[0].StudyId)
|
||||
} else {
|
||||
this.fusionForm.studyId = ''
|
||||
this.ctSeries = []
|
||||
this.petSeries = []
|
||||
}
|
||||
this.fusionForm.visitTaskId = this.taskList[this.activeTaskIndex].VisitTaskId
|
||||
this.fusionForm.readingTaskState = this.taskList[this.activeTaskIndex].ReadingTaskState
|
||||
this.fusionForm.taskBlindName = this.taskList[this.activeTaskIndex].TaskBlindName
|
||||
this.fusionForm.subjectCode = this.taskList[this.activeTaskIndex].SubjectCode
|
||||
this.fusionForm.isBaseLineTask = this.taskList[this.activeTaskIndex].IsBaseLineTask
|
||||
this.fusionForm.isCurrentTask = this.taskList[this.activeTaskIndex].IsCurrentTask
|
||||
},
|
||||
getStudyList(obj) {
|
||||
if (obj) {
|
||||
var studyList = obj.StudyList || []
|
||||
studyList = studyList.filter(i => !i.IsCriticalSequence && i.Modalities.indexOf('CT') !== -1 && i.Modalities.indexOf('PT') !== -1)
|
||||
if (studyList.length === 0) return
|
||||
this.studyList = studyList
|
||||
}
|
||||
},
|
||||
handleSubmitFusionSeries() {
|
||||
this.$refs['fusionForm'].validate((valid) => {
|
||||
if (!valid) return
|
||||
if (Object.keys(this.fusionForm.ctSeriesInfo).length === 0 || Object.keys(this.fusionForm.petSeriesInfo).length === 0) {
|
||||
// '请选择序列信息!'
|
||||
this.$confirm(this.$t('trials:lugano:fusionDialog:message:checkSeries'), this.$t('trials:lugano:fusionDialog:warning'), {
|
||||
showCancelButton: false,
|
||||
type: 'warning'
|
||||
}).then(() => { }).catch(() => { })
|
||||
return
|
||||
}
|
||||
var count = Math.abs(this.fusionForm.ctSeriesInfo.InstanceCount - this.fusionForm.petSeriesInfo.InstanceCount)
|
||||
if (count > 10) {
|
||||
// '选择的两组序列,影像数存在较大差距, 是否继续?'
|
||||
this.$confirm(this.$t('trials:lugano:fusionDialog:message:validSeries'), this.$t('trials:lugano:fusionDialog:warning'), {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
this.fusion()
|
||||
}).catch(() => { })
|
||||
} else {
|
||||
this.fusion()
|
||||
}
|
||||
})
|
||||
},
|
||||
fusion() {
|
||||
this.$emit('fusion', { ct: this.fusionForm.ctSeriesInfo, pt: this.fusionForm.petSeriesInfo })
|
||||
},
|
||||
handleCancel() {
|
||||
this.$emit('close')
|
||||
},
|
||||
handleTaskIdChange(v) {
|
||||
var idx = this.taskList.findIndex(i => i.VisitTaskId === v)
|
||||
this.studyList = idx > -1 ? this.getStudyList(this.taskList[idx]) : []
|
||||
this.fusionForm.taskBlindName = idx > -1 ? this.taskList[idx].TaskBlindName : ''
|
||||
this.fusionForm.isBaseLineTask = idx > -1 ? this.taskList[idx].IsBaseLineTask : null
|
||||
this.studyList = idx > -1 ? this.taskList[idx].StudyList : null
|
||||
this.fusionForm.studyId = ''
|
||||
this.fusionForm.defaultStudyId = idx > -1 ? this.taskList[idx].StudyId : ''
|
||||
this.fusionForm.defaultCTSeriesId = idx > -1 ? this.taskList[idx].CTSeriesId : ''
|
||||
this.fusionForm.defaultPTSeriesId = idx > -1 ? this.taskList[idx].PTSeriesId : ''
|
||||
this.ctSeries = []
|
||||
this.petSeries = []
|
||||
},
|
||||
handleStudyIdChange(v) {
|
||||
var i = this.studyList.findIndex(i => i.StudyId === v)
|
||||
if (i === -1) {
|
||||
this.ctSeries = []
|
||||
this.petSeries = []
|
||||
} else {
|
||||
var seriesList = this.studyList[i].SeriesList
|
||||
var series = seriesList.filter(series => series.Modality === 'CT')
|
||||
this.ctSeries = series.sort((a, b) => b.instanceCount - a.instanceCount)
|
||||
|
||||
series = seriesList.filter(series => series.Modality === 'PT')
|
||||
this.petSeries = series.sort((a, b) => b.instanceCount - a.instanceCount)
|
||||
}
|
||||
},
|
||||
handleCTSelectionChange(rows) {
|
||||
if (rows.length > 0) {
|
||||
this.fusionForm.ctSeriesInfo = Object.assign({}, rows[0])
|
||||
} else {
|
||||
this.fusionForm.ctSeriesInfo = {}
|
||||
}
|
||||
},
|
||||
handleCTSelect(selection) {
|
||||
if (selection.length > 1) {
|
||||
const del_row = selection.shift()
|
||||
this.$refs.ctSeries.toggleRowSelection(del_row, false)
|
||||
}
|
||||
},
|
||||
handlePTSelectionChange(rows) {
|
||||
if (rows.length > 0) {
|
||||
this.fusionForm.petSeriesInfo = Object.assign({}, rows[0])
|
||||
} else {
|
||||
this.fusionForm.petSeriesInfo = {}
|
||||
}
|
||||
},
|
||||
handlePTSelect(selection) {
|
||||
if (selection.length > 1) {
|
||||
const del_row = selection.shift()
|
||||
this.$refs.petSeries.toggleRowSelection(del_row, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.series-table {
|
||||
::v-deep.el-table {
|
||||
background-color: #1e1e1e !important;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
|
||||
::v-deep.el-table td.el-table__cell,
|
||||
.el-table th.el-table__cell.is-leaf {
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
}
|
||||
|
||||
.el-table--border::after,
|
||||
.el-table--group::after,
|
||||
.el-table::before {
|
||||
background-color: #1e1e1e;
|
||||
}
|
||||
|
||||
::v-deep.el-table__header-wrapper {
|
||||
th {
|
||||
background-color: #1e1e1e !important;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.el-table__body-wrapper {
|
||||
tr {
|
||||
background-color: #1e1e1e !important;
|
||||
color: #dfdfdf;
|
||||
}
|
||||
|
||||
tr:hover>td {
|
||||
background-color: #1e1e1e !important;
|
||||
}
|
||||
}
|
||||
|
||||
::v-deep.el-table__empty-block {
|
||||
background-color: #1e1e1e !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,970 @@
|
||||
<template>
|
||||
<div ref="viewport-fusion" class="viewport-wrapper" @mouseup="sliderMouseup" @mousemove="sliderMousemove"
|
||||
@mouseleave="sliderMouseleave" :style="{ color: series.Modality === 'PT' || isMip ? '#666' : '#ddd' }">
|
||||
<div v-if="series && taskInfo" class="left-top-text">
|
||||
<div v-if="taskInfo.IsExistsClinicalData && !isMip && !isFusion" class="cd-info"
|
||||
:title="$t('trials:reading:button:clinicalData')">
|
||||
<svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon"
|
||||
@click.stop="viewCD(series.TaskInfo.VisitTaskId)" />
|
||||
</div>
|
||||
<h2 v-if="taskInfo.IsReadingShowSubjectInfo && series.TaskInfo" class="subject-info">
|
||||
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
|
||||
</h2>
|
||||
<div v-if="!isMip && !isFusion">Series: #{{ series.SeriesNumber }}</div>
|
||||
<div v-if="series.Stack && !isMip">Image: #{{ `${series.SliceIndex + 1}/${series.Stack.length}` }}</div>
|
||||
<div v-if="!isMip && !isFusion">{{ series.Modality }}</div>
|
||||
</div>
|
||||
<!-- <div v-if="series && taskInfo && taskInfo.IsReadingTaskViewInOrder === 1 && series.TaskInfo && !isMip && !isFusion"
|
||||
class="top-center-tool">
|
||||
<div class="toggle-visit-container">
|
||||
<div class="arrw_icon"
|
||||
:style="{ cursor: series.TaskInfo.VisitTaskNum !== 0 ? 'pointer' : 'not-allowed', color: series.TaskInfo.VisitTaskNum !== 0 ? '#fff' : '#6b6b6b' }"
|
||||
@click.stop.prevent="toggleTask($event, series.TaskInfo.VisitTaskNum, -1)"
|
||||
@dblclick.stop="preventDefault($event)">
|
||||
<i class="el-icon-caret-left" />
|
||||
</div>
|
||||
<div class="arrow_text">
|
||||
{{ series.TaskInfo.TaskBlindName }}
|
||||
</div>
|
||||
<div class="arrw_icon"
|
||||
:style="{ cursor: series.TaskInfo.VisitTaskNum < taskInfo.VisitNum ? 'pointer' : 'not-allowed', color: series.TaskInfo.VisitTaskNum < taskInfo.VisitNum ? '#fff' : '#6b6b6b' }"
|
||||
@click.stop.prevent="toggleTask($event, series.TaskInfo.VisitTaskNum, 1)"
|
||||
@dblclick.stop="preventDefault($event)">
|
||||
<i class="el-icon-caret-right" />
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
<div v-if="series && !isMip && !isFusion" class="right-top-text">
|
||||
<div>{{ series.Description }}</div>
|
||||
</div>
|
||||
<div v-if="series" class="left-bottom-text">
|
||||
<div v-show="mousePosition.index.length > 0 && !isMip">
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
|
||||
</div>
|
||||
<div
|
||||
v-if="(series.Modality === 'CT' || series.Modality === 'DR' || series.Modality === 'CR') && mousePosition.value && !isMip && !isFusion">
|
||||
HU: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-else-if="(series.Modality === 'PT' && mousePosition.value) && !isMip && !isFusion">
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ? mousePosition.value.toFixed(3) : mousePosition.value.toFixed(digitPlaces)
|
||||
}}
|
||||
</div>
|
||||
<div v-else-if="mousePosition.value && !isMip && !isFusion">
|
||||
Density: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-show="imageInfo.size && !isMip && !isFusion">
|
||||
W*H: {{ imageInfo.size }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series && !isMip" class="right-bottom-text">
|
||||
<div v-show="imageInfo.location && !isFusion">Location: {{ `${Number(imageInfo.location).toFixed(digitPlaces)} mm`
|
||||
}}</div>
|
||||
<div v-show="series.SliceThickness && !isFusion">Slice Thickness: {{
|
||||
`${Number(series.SliceThickness).toFixed(digitPlaces)} mm`
|
||||
}}</div>
|
||||
<div v-show="imageInfo.wwwc">WW/WL: {{ imageInfo.wwwc }}</div>
|
||||
</div>
|
||||
<div class="orientation-top" v-if="!isMip">
|
||||
{{ markers.top }}
|
||||
</div>
|
||||
<div class="orientation-right" v-if="!isMip">
|
||||
{{ markers.right }}
|
||||
</div>
|
||||
|
||||
<div class="orientation-bottom" v-if="!isMip">
|
||||
{{ markers.bottom }}
|
||||
</div>
|
||||
<div class="orientation-left" v-if="!isMip">
|
||||
{{ markers.left }}
|
||||
</div>
|
||||
<div v-if="isFusion" class="color_bar">
|
||||
<canvas :id="`colorBar_Canvas_${viewportId}`" />
|
||||
<!-- <div id="colorBar_Canvas" /> -->
|
||||
</div>
|
||||
<div v-if="isMip" id="rotateBar" ref="rotateBar" class="rotate_slider_box" @click.stop="clickRotate($event)">
|
||||
<div id="rotateSlider" :style="{ left: rotateBarLeft + 'px' }" class="box" @click.stop.prevent="() => { return }"
|
||||
@mousedown.stop="rotateBarMousedown($event)" />
|
||||
</div>
|
||||
<div ref="sliderBox" class="right-slider-box" @click.stop="clickSlider($event)" v-show="!isMip">
|
||||
<div :style="{ top: sliderInfo.height + '%' }" class="slider" @click.stop.prevent="() => { return }"
|
||||
@mousedown.stop="sliderMousedown($event)" />
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import * as cornerstonejs from '@cornerstonejs/core'
|
||||
import {
|
||||
// RenderingEngine,
|
||||
Enums,
|
||||
// imageLoader,
|
||||
metaData,
|
||||
getRenderingEngine,
|
||||
volumeLoader,
|
||||
// eventTarget,
|
||||
utilities as csUtils,
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
import { utilities as cstUtils } from '@cornerstonejs/tools';
|
||||
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader';
|
||||
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
|
||||
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
|
||||
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||
import setPetTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetTransferFunctionForVolumeActor'
|
||||
import { setPetColorMapTransferFunctionForVolumeActor } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetColorMapTransferFunctionForVolumeActor'
|
||||
const {
|
||||
ToolGroupManager,
|
||||
MIPJumpToClickTool,
|
||||
VolumeRotateTool,
|
||||
Enums: csToolsEnums,
|
||||
} = cornerstoneTools
|
||||
const { BlendModes, OrientationAxis } = Enums;
|
||||
const { MouseBindings } = csToolsEnums
|
||||
const { getColormap, getColormapNames } = csUtils.colormap;
|
||||
const { ViewportColorbar } = cstUtils.voi.colorbar;
|
||||
const { ColorbarRangeTextPosition } = cstUtils.voi.colorbar.Enums;
|
||||
import { vec3, mat4 } from 'gl-matrix'
|
||||
export default {
|
||||
name: 'ImageViewport',
|
||||
props: {
|
||||
renderingEngineId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
viewportId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
viewportIndex: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
element: '',
|
||||
series: {},
|
||||
ctSeries: {},
|
||||
petSeries: {},
|
||||
isFusion: false,
|
||||
isMip: false,
|
||||
taskInfo: null,
|
||||
sliderInfo: {
|
||||
oldB: null,
|
||||
oldM: null,
|
||||
isMove: false,
|
||||
height: 0
|
||||
},
|
||||
mousePosition: {
|
||||
index: [],
|
||||
value: null,
|
||||
modalityUnit: '',
|
||||
world: []
|
||||
},
|
||||
imageInfo: {
|
||||
zoom: null,
|
||||
size: null,
|
||||
location: null,
|
||||
sliceThickness: null,
|
||||
wwwc: null
|
||||
},
|
||||
digitPlaces: 2,
|
||||
orientationMarkers: [],
|
||||
originalMarkers: [],
|
||||
markers: { top: '', right: '', bottom: '', left: '' },
|
||||
playClipState: false,
|
||||
wwwcIdx: 2,
|
||||
presetName: '',
|
||||
volumeId: null,
|
||||
defaultWindowLevel: {},
|
||||
Colorbar: null,
|
||||
rotateAngle: 0,
|
||||
rotateBarLeft: 0,
|
||||
rotateBarInfo: {
|
||||
initX: null,
|
||||
initLeft: null,
|
||||
isMove: false
|
||||
},
|
||||
ptVolumeId: null,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.$nextTick(() => {
|
||||
this.initViewport()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
initViewport() {
|
||||
this.element = this.$refs['viewport-fusion']
|
||||
const resizeObserver = new ResizeObserver(() => {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
if (renderingEngine) {
|
||||
renderingEngine.resize(true, false)
|
||||
}
|
||||
})
|
||||
this.element.oncontextmenu = (e) => e.preventDefault()
|
||||
// resizeObserver.observe(this.element)
|
||||
this.element.addEventListener("CORNERSTONE_VOLUME_NEW_IMAGE", this.stackNewImage)
|
||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||
|
||||
this.element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.cornerstoneToolsMouseMove)
|
||||
this.element.addEventListener(cornerstoneTools.Enums.Events.MOUSE_WHEEL, this.handletoolsMouseWheel)
|
||||
this.element.addEventListener('mouseleave', () => {
|
||||
this.mousePosition.index = []
|
||||
this.mousePosition.value = null
|
||||
})
|
||||
document.addEventListener('mouseup', () => {
|
||||
this.sliderMouseup()
|
||||
if (this.isMip) {
|
||||
this.rotateBarMouseup()
|
||||
}
|
||||
})
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
this.sliderMousemove(e)
|
||||
if (this.isMip) {
|
||||
this.rotateBarMousemove(e)
|
||||
}
|
||||
})
|
||||
// console.log(cornerstoneTools)
|
||||
// element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
},
|
||||
stackNewImage(e) {
|
||||
const { detail } = e
|
||||
this.series.SliceIndex = detail.imageIndex
|
||||
this.sliderInfo.height = detail.imageIndex * 100 / detail.numberOfSlices
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
let imageId = viewport.getCurrentImageId()
|
||||
if (imageId) {
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', imageId)
|
||||
this.imageInfo.size = `${imagePlaneModule.columns}*${imagePlaneModule.rows}`
|
||||
this.imageInfo.location = imagePlaneModule.sliceLocation
|
||||
this.getOrientationMarker()
|
||||
// this.$emit('renderAnnotations', this.series)
|
||||
let properties = viewport.getProperties()
|
||||
if (this.isFusion) {
|
||||
properties = viewport.getProperties(this.ptVolumeId)
|
||||
}
|
||||
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const windowWidth = upper - lower
|
||||
const windowCenter = (upper + lower) / 2
|
||||
this.defaultWindowLevel.windowWidth = windowWidth
|
||||
this.defaultWindowLevel.windowCenter = windowCenter
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
}
|
||||
// const toolGroupId = `viewport-${this.viewportIndex}`
|
||||
// const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
// toolGroup.setToolEnabled('ScaleOverlay')
|
||||
}
|
||||
|
||||
},
|
||||
setFullScreen(index) {
|
||||
setTimeout(() => {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: index })
|
||||
viewport.render()
|
||||
})
|
||||
},
|
||||
voiModified(e) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
let properties = viewport.getProperties()
|
||||
if (this.isFusion) {
|
||||
properties = viewport.getProperties(this.volumeId)
|
||||
}
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
)
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
this.$emit('upperRangeChange', Math.round(windowWidth))
|
||||
}
|
||||
},
|
||||
getOrientationMarker() {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const { viewUp, viewPlaneNormal } = viewport.getCamera()
|
||||
|
||||
const viewRight = vec3.create()
|
||||
vec3.cross(viewRight, viewUp, viewPlaneNormal)
|
||||
|
||||
const columnCosines = [-viewUp[0], -viewUp[1], -viewUp[2]]
|
||||
const rowCosines = viewRight
|
||||
const rowString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(rowCosines)
|
||||
const columnString = cornerstoneTools.utilities.orientation.getOrientationStringLPS(columnCosines)
|
||||
const oppositeRowString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(rowString)
|
||||
const oppositeColumnString = cornerstoneTools.utilities.orientation.invertOrientationStringLPS(columnString)
|
||||
this.markers.top = oppositeColumnString
|
||||
this.markers.right = rowString
|
||||
this.markers.bottom = columnString
|
||||
this.markers.left = oppositeRowString
|
||||
this.orientationMarkers = [oppositeColumnString, rowString, columnString, oppositeRowString]
|
||||
if (this.originalMarkers.length === 0) {
|
||||
this.originalMarkers = [...this.orientationMarkers]
|
||||
}
|
||||
},
|
||||
setMarkers() {
|
||||
const markers = [...this.orientationMarkers]
|
||||
for (const key in this.markers) {
|
||||
const v = markers.shift(0)
|
||||
this.markers[key] = v
|
||||
}
|
||||
},
|
||||
resetOrientationMarkers() {
|
||||
if (this.originalMarkers.length > 0) {
|
||||
this.orientationMarkers = [...this.originalMarkers]
|
||||
this.setMarkers()
|
||||
}
|
||||
},
|
||||
rotateOrientationMarkers(type) {
|
||||
if (this.orientationMarkers.length > 0) {
|
||||
if (type === 1) {
|
||||
this.resetOrientationMarkers()
|
||||
return
|
||||
}
|
||||
const markers = [...this.orientationMarkers]
|
||||
if (type === 2) {
|
||||
// 垂直翻转
|
||||
this.orientationMarkers[0] = markers[2]
|
||||
this.orientationMarkers[2] = markers[0]
|
||||
} else if (type === 3) {
|
||||
// 水平翻转
|
||||
this.orientationMarkers[1] = markers[3]
|
||||
this.orientationMarkers[3] = markers[1]
|
||||
} else if (type === 4) {
|
||||
// 左转90度
|
||||
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
|
||||
} else if (type === 5) {
|
||||
// 右转90度
|
||||
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
|
||||
}
|
||||
this.setMarkers()
|
||||
}
|
||||
},
|
||||
toggleClipPlay(isPlay, framesPerSecond) {
|
||||
this.playClipState = isPlay
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
if (isPlay) {
|
||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: false })
|
||||
} else {
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
}
|
||||
},
|
||||
scrollPage(type) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const currentImageIdIndex = viewport.getCurrentImageIdIndex()
|
||||
const numImages = viewport.getImageIds().length
|
||||
let newImageIdIndex = null
|
||||
if (type === 0) {
|
||||
newImageIdIndex = 0
|
||||
} else if (type === -1) {
|
||||
newImageIdIndex = currentImageIdIndex === 0 ? currentImageIdIndex : currentImageIdIndex - 1
|
||||
} else if (type === 1) {
|
||||
newImageIdIndex = currentImageIdIndex === numImages - 1 ? currentImageIdIndex : currentImageIdIndex + 1
|
||||
} else if (type === 99999) {
|
||||
newImageIdIndex = numImages - 1
|
||||
}
|
||||
// viewport.setImageIdIndex(newImageIdIndex)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: newImageIdIndex })
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
},
|
||||
setZoom(ratio) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
const zoom = viewport.getZoom()
|
||||
if (ratio > 0) {
|
||||
viewport.setZoom(zoom * 1.05)
|
||||
} else {
|
||||
viewport.setZoom(zoom / 1.05)
|
||||
}
|
||||
viewport.render()
|
||||
},
|
||||
resize(forceFitToWindow) {
|
||||
console.log('resize: ', forceFitToWindow)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (!forceFitToWindow) {
|
||||
viewport.setZoom(0.5)
|
||||
viewport.render()
|
||||
} else {
|
||||
viewport.setZoom(1)
|
||||
viewport.render()
|
||||
}
|
||||
},
|
||||
voiChange(v) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const voiRange = { lower: 0, upper: v }
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (!viewport) return
|
||||
let volumeId = this.isFusion ? this.ptVolumeId : this.volumeId
|
||||
const viewportsContainingVolumeUID = csUtils.getViewportsWithVolumeId(
|
||||
volumeId,
|
||||
viewport.renderingEngineId
|
||||
)
|
||||
|
||||
viewport.setProperties({ voiRange }, volumeId)
|
||||
viewportsContainingVolumeUID.forEach((vp) => {
|
||||
vp.render()
|
||||
// this.$refs[vp.id].voiModified()
|
||||
this.voiModified()
|
||||
})
|
||||
},
|
||||
renderColorBar(presetName) {
|
||||
var colorMap = null
|
||||
this.Colorbar = null
|
||||
if (presetName === 'hsv') {
|
||||
colorMap = vtkColorMaps.getPresetByName(presetName)
|
||||
} else {
|
||||
colorMap = getColormap(presetName)
|
||||
}
|
||||
if (!colorMap) return false
|
||||
// let colormaps = getColormapNames().map(name => getColormap(name))
|
||||
// console.log(colormaps)
|
||||
// const canvas = document.getElementById('colorBar_Canvas')
|
||||
// this.Colorbar = new ViewportColorbar({
|
||||
// id: this.volumeId,
|
||||
// element: this.element,
|
||||
// container: canvas,
|
||||
// colormaps,
|
||||
// activeColormapName: presetName,
|
||||
// ticks: {
|
||||
// position: ColorbarRangeTextPosition.Left,
|
||||
// style: {
|
||||
// font: '12px Arial',
|
||||
// color: '#fff',
|
||||
// maxNumTicks: 8,
|
||||
// tickSize: 5,
|
||||
// tickWidth: 1,
|
||||
// labelMargin: 3,
|
||||
// },
|
||||
// },
|
||||
// });
|
||||
const rgbPoints = colorMap.RGBPoints
|
||||
const canvas = document.getElementById(`colorBar_Canvas_${this.viewportId}`)
|
||||
if (!canvas) return false
|
||||
const ctx = canvas.getContext('2d')
|
||||
const canvasWidth = 160
|
||||
const canvasHeight = 5
|
||||
const rectWidth = 160
|
||||
const rectHeight = canvasHeight
|
||||
canvas.width = canvasWidth
|
||||
canvas.height = canvasHeight
|
||||
const gradient = ctx.createLinearGradient(0, 0, rectWidth, 0)
|
||||
for (let i = 0; i < rgbPoints.length; i += 4) {
|
||||
let position = 0
|
||||
if (rgbPoints[0] === -1) {
|
||||
position = (rgbPoints[i] + 1) / 2
|
||||
} else {
|
||||
position = rgbPoints[i]
|
||||
}
|
||||
const color = `rgb(${parseInt(rgbPoints[i + 1] * 255)}, ${parseInt(rgbPoints[i + 2] * 255)}, ${parseInt(rgbPoints[i + 3] * 255)})`
|
||||
gradient.addColorStop(position, color)
|
||||
}
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, 0, rectWidth, rectHeight)
|
||||
},
|
||||
setPreset(presetName) {
|
||||
this.presetName = presetName
|
||||
},
|
||||
setColorMap(presetName) {
|
||||
if (this.Colorbar) {
|
||||
this.Colorbar.activeColormapName = presetName;
|
||||
}
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
viewport.setProperties({ colormap: { name: presetName } }, this.volumeId)
|
||||
viewport.render()
|
||||
},
|
||||
async prefetchMetadataInformation(imageIdsToPrefetch) {
|
||||
let taskPromises = []
|
||||
for (let i = 0; i < imageIdsToPrefetch.length; i++) {
|
||||
taskPromises.push(cornerstoneDICOMImageLoader.wadouri.loadImage(imageIdsToPrefetch[i]).promise)
|
||||
if (taskPromises.length >= 6 || i === imageIdsToPrefetch.length - 1) {
|
||||
await Promise.all(taskPromises)
|
||||
taskPromises = []
|
||||
}
|
||||
}
|
||||
},
|
||||
async createImageIdsAndCacheMetaData(obj) {
|
||||
await createImageIdsAndCacheMetaData({
|
||||
modality: obj.Modality,
|
||||
imageIds: obj.ImageIds
|
||||
})
|
||||
},
|
||||
async setSeriesInfo(obj, option = {}) {
|
||||
try {
|
||||
let { data, volumeId } = obj
|
||||
if (this.series && data.Id === this.series.Id && data.Description === this.series.Description) {
|
||||
data.SliceIndex = this.series.SliceIndex
|
||||
}
|
||||
this.ptVolumeId = null
|
||||
this.series = {}
|
||||
let { isFusion, isMip, colorMap } = option
|
||||
this.isFusion = isFusion;
|
||||
this.isMip = isMip;
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (this.isFusion) {
|
||||
this.$nextTick(() => {
|
||||
this.renderColorBar(this.presetName)
|
||||
})
|
||||
let { ct, data, ctVolumeId, ptVolumeId, fusionVolumeId } = obj
|
||||
this.series = { ...data }
|
||||
this.ctSeries = { ...ct }
|
||||
this.petSeries = { ...data }
|
||||
// const maxCount = Math.max(this.ctSeries.ImageIds.length, this.petSeries.ImageIds.length)
|
||||
// this.$set(this.ctSeries, 'imageMaxLength', maxCount)
|
||||
// this.$set(this.petSeries, 'imageMaxLength', maxCount)
|
||||
// await this.createImageIdsAndCacheMetaData(this.ctSeries)
|
||||
// await this.createImageIdsAndCacheMetaData(this.petSeries)
|
||||
this.volumeId = ptVolumeId
|
||||
this.ptVolumeId = fusionVolumeId
|
||||
await viewport
|
||||
.setVolumes([
|
||||
{
|
||||
volumeId: this.ptVolumeId, callback: (r) => {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
console.log("融合pet渲染成功");
|
||||
}
|
||||
},
|
||||
{
|
||||
volumeId: ctVolumeId, callback: (r) => {
|
||||
setCtTransferFunctionForVolumeActor(r)
|
||||
console.log("融合ct渲染成功")
|
||||
}
|
||||
},
|
||||
{
|
||||
volumeId: this.volumeId, callback: (r) => {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
console.log("融合pet渲染成功");
|
||||
}
|
||||
},
|
||||
]).then(res => {
|
||||
if (colorMap) {
|
||||
this.setColorMap(this.presetName)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.series = { ...data }
|
||||
this.volumeId = volumeId
|
||||
if (this.isMip) {
|
||||
let { volume } = obj
|
||||
const ptVolumeDimensions = volume.dimensions;
|
||||
const slabThickness = Math.sqrt(
|
||||
ptVolumeDimensions[0] * ptVolumeDimensions[0] +
|
||||
ptVolumeDimensions[1] * ptVolumeDimensions[1] +
|
||||
ptVolumeDimensions[2] * ptVolumeDimensions[2]
|
||||
);
|
||||
viewport
|
||||
.setVolumes([{
|
||||
volumeId: this.volumeId,
|
||||
callback: (r) => {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r)
|
||||
console.log("mip渲染成功")
|
||||
},
|
||||
slabThickness,
|
||||
blendMode: BlendModes.MAXIMUM_INTENSITY_BLEND,
|
||||
defaultOptions: {
|
||||
orientation: OrientationAxis.CORONAL
|
||||
}
|
||||
}]).then(res => {
|
||||
if (colorMap) {
|
||||
this.setColorMap(this.presetName)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
viewport
|
||||
.setVolumes([{
|
||||
volumeId: this.volumeId, callback: (r) => {
|
||||
if (this.series.Modality === 'PT') {
|
||||
setPetColorMapTransferFunctionForVolumeActor(r, true)
|
||||
} else {
|
||||
setCtTransferFunctionForVolumeActor(r)
|
||||
}
|
||||
console.log("渲染成功")
|
||||
}
|
||||
}]).then(res => {
|
||||
if (colorMap) {
|
||||
this.setColorMap(this.presetName)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
viewport.render()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
},
|
||||
cornerstoneToolsMouseMove(e) {
|
||||
const { currentPoints } = e.detail
|
||||
const worldPoint = currentPoints.world
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const imageData = viewport.getImageData()
|
||||
if (!imageData) return
|
||||
const index = imageData.imageData.worldToIndex(worldPoint)
|
||||
index[0] = Math.floor(index[0])
|
||||
index[1] = Math.floor(index[1])
|
||||
index[2] = Math.floor(index[2])
|
||||
this.mousePosition.index = index
|
||||
},
|
||||
toggleTask(evt, visitTaskNum, i) {
|
||||
this.$emit('activeViewport', this.viewportIndex)
|
||||
const num = visitTaskNum + i
|
||||
if (num >= 0 && num <= this.taskInfo.VisitNum) {
|
||||
this.$emit('toggleTaskByViewport', { series: this.series, visitTaskNum: num })
|
||||
}
|
||||
|
||||
evt.stopImmediatePropagation()
|
||||
evt.stopPropagation()
|
||||
evt.preventDefault()
|
||||
},
|
||||
viewCD(taskId) {
|
||||
this.$emit('previewCD', taskId)
|
||||
},
|
||||
setWwwcIdx(idx) {
|
||||
this.wwwcIdx = idx
|
||||
},
|
||||
clickSlider(e) {
|
||||
const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.height = height
|
||||
let sliceIdx = Math.trunc(this.series.Stack.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
// viewport.setImageIdIndex(sliceIdx)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseup(e) {
|
||||
this.sliderInfo.isMove = false
|
||||
},
|
||||
sliderMousedown(e) {
|
||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
|
||||
this.sliderInfo.oldM = e.clientY
|
||||
this.sliderInfo.isMove = true
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
sliderMousemove(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
const delta = this.sliderInfo.oldB - (this.sliderInfo.oldM - e.clientY)
|
||||
const boxHeight = this.$refs['sliderBox'].clientHeight
|
||||
if (delta < 0) return
|
||||
if (delta > boxHeight) return
|
||||
const height = delta * 100 / boxHeight
|
||||
let sliceIdx = Math.trunc(this.series.Stack.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
this.sliderInfo.height = height
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
// viewport.setImageIdIndex(sliceIdx)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseleave(e) {
|
||||
if (!this.sliderInfo.isMove) return
|
||||
this.sliderInfo.isMove = false
|
||||
},
|
||||
handletoolsMouseWheel(e) {
|
||||
const { viewportId, wheel } = e.detail
|
||||
if (this.isMip) {
|
||||
const container = document.getElementById('rotateBar')
|
||||
const slider = document.getElementById('rotateSlider')
|
||||
const containerWidth = container.offsetWidth
|
||||
const sliderWidth = slider.offsetWidth
|
||||
const maxX = containerWidth - sliderWidth
|
||||
const { direction } = wheel
|
||||
|
||||
var x = Math.trunc(30 * ((containerWidth - sliderWidth) / 360))
|
||||
if (direction > 0 && (this.rotateBarLeft + x) > maxX) {
|
||||
this.rotateBarLeft = x - (containerWidth - sliderWidth - this.rotateBarLeft)
|
||||
} else if (direction < 0 && (this.rotateBarLeft < x)) {
|
||||
this.rotateBarLeft = containerWidth - (x - this.rotateBarLeft + sliderWidth)
|
||||
} else {
|
||||
this.rotateBarLeft = x * direction + this.rotateBarLeft
|
||||
}
|
||||
}
|
||||
},
|
||||
rotateBarMouseup(e) {
|
||||
this.rotateBarInfo.isMove = false
|
||||
},
|
||||
rotateBarMousemove(e) {
|
||||
// 滚动旋转
|
||||
if (!this.rotateBarInfo.isMove) return
|
||||
const container = document.getElementById('rotateBar')
|
||||
const slider = document.getElementById('rotateSlider')
|
||||
const containerWidth = container.offsetWidth
|
||||
const sliderWidth = slider.offsetWidth
|
||||
let x = Math.trunc(e.clientX - this.rotateBarInfo.initX + this.rotateBarInfo.initLeft)
|
||||
if (x < 0) x = 0
|
||||
if (x > containerWidth - sliderWidth) x = containerWidth - sliderWidth
|
||||
const deltaX = x - this.rotateBarLeft
|
||||
const angle = Math.sin((deltaX * (360 / (containerWidth - sliderWidth))) * Math.PI / 180)
|
||||
this.rotate(angle)
|
||||
this.rotateBarLeft = x
|
||||
},
|
||||
rotateBarMousedown(e) {
|
||||
this.rotateBarInfo.initLeft = e.srcElement.offsetLeft
|
||||
this.rotateBarInfo.initX = e.clientX
|
||||
this.rotateBarInfo.isMove = true
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
rotate(angle) {
|
||||
let renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
let viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const camera = viewport.getCamera()
|
||||
const { viewUp, position, focalPoint } = camera
|
||||
const [cx, cy, cz] = focalPoint
|
||||
const [ax, ay, az] = [0, 0, 1]
|
||||
const newPosition = [0, 0, 0]
|
||||
const newFocalPoint = [0, 0, 0]
|
||||
const newViewUp = [0, 0, 0]
|
||||
|
||||
const transform = mat4.identity(new Float32Array(16))
|
||||
mat4.translate(transform, transform, [cx, cy, cz])
|
||||
mat4.rotate(transform, transform, angle, [ax, ay, az])
|
||||
mat4.translate(transform, transform, [-cx, -cy, -cz])
|
||||
vec3.transformMat4(newPosition, position, transform)
|
||||
vec3.transformMat4(newFocalPoint, focalPoint, transform)
|
||||
|
||||
mat4.identity(transform)
|
||||
mat4.rotate(transform, transform, angle, [ax, ay, az])
|
||||
vec3.transformMat4(newViewUp, viewUp, transform)
|
||||
|
||||
viewport.setCamera({
|
||||
position: newPosition,
|
||||
viewUp: newViewUp,
|
||||
focalPoint: newFocalPoint
|
||||
})
|
||||
|
||||
viewport.render()
|
||||
},
|
||||
clickRotate(e) {
|
||||
// console.log('clickRotate')
|
||||
const container = document.getElementById('rotateBar')
|
||||
const containerWidth = container.offsetWidth
|
||||
const slider = document.getElementById('rotateSlider')
|
||||
const sliderWidth = slider.offsetWidth
|
||||
const x = Math.trunc(e.offsetX)
|
||||
const deltaX = x - this.rotateBarLeft
|
||||
const angle = Math.sin((deltaX * (360 / (containerWidth - sliderWidth))) * Math.PI / 180)
|
||||
this.rotate(angle)
|
||||
this.rotateBarLeft = x
|
||||
},
|
||||
preventDefault(e) {
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.viewport-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: relative;
|
||||
|
||||
.left-top-text {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
top: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
|
||||
.cd-info {
|
||||
// color: #ddd;
|
||||
font-size: 18px;
|
||||
}
|
||||
|
||||
.subject-info {
|
||||
color: #f44336;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.top-center-tool {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
|
||||
.toggle-visit-container {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.arrw_icon {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
|
||||
.arrow_text {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding: 0 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.right-top-text {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
top: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.left-bottom-text {
|
||||
position: absolute;
|
||||
left: 5px;
|
||||
bottom: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.right-bottom-text {
|
||||
position: absolute;
|
||||
right: 5px;
|
||||
bottom: 5px;
|
||||
// color: #ddd;
|
||||
z-index: 1;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.right-slider-box {
|
||||
position: absolute;
|
||||
right: 1px;
|
||||
height: calc(100% - 140px);
|
||||
transform: translateY(-50%);
|
||||
top: calc(50% - 30px);
|
||||
width: 10px;
|
||||
background: #333;
|
||||
z-index: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.right-slider-box:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
left: 0;
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
background: #333;
|
||||
}
|
||||
|
||||
.slider {
|
||||
height: 20px;
|
||||
width: 100%;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
z-index: 10;
|
||||
background: #9e9e9e;
|
||||
cursor: move
|
||||
}
|
||||
|
||||
.orientation-top {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 30px;
|
||||
color: #f44336;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.orientation-bottom {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: 15px;
|
||||
color: #f44336;
|
||||
transform: translateX(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.orientation-left {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: 15px;
|
||||
color: #f44336;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.orientation-right {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 15px;
|
||||
color: #f44336;
|
||||
transform: translateY(-50%);
|
||||
z-index: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.color_bar {
|
||||
position: absolute;
|
||||
transform: rotate(-90deg);
|
||||
transform-origin: right;
|
||||
left: -150px;
|
||||
top: 30%;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.rotate_slider_box {
|
||||
position: absolute;
|
||||
width: 380px;
|
||||
height: 10px;
|
||||
bottom: 5px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #333;
|
||||
z-index: 10;
|
||||
cursor: pointer;
|
||||
|
||||
.box {
|
||||
z-index: 10;
|
||||
background: #9e9e9e;
|
||||
height: 100%;
|
||||
width: 20px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
cursor: move
|
||||
}
|
||||
}
|
||||
</style>
|
||||
File diff suppressed because it is too large
Load Diff
@@ -208,6 +208,8 @@
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
:visitTaskId="visitTaskId"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
@setFormItemData="setFormItemData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -266,6 +268,7 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
console.log('formItemChange')
|
||||
if (question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
} else {
|
||||
@@ -315,4 +318,8 @@ export default {
|
||||
::v-deep .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
// ::v-deep .el-radio__input.is-disabled.is-checked .el-radio__inner {
|
||||
// background-color: #428bca;
|
||||
// border-color: #428bca;
|
||||
// }
|
||||
</style>
|
||||
|
||||
+583
-482
File diff suppressed because it is too large
Load Diff
@@ -245,7 +245,7 @@
|
||||
:title="additionalAssessmentsDig.title"
|
||||
width="600px"
|
||||
>
|
||||
<AdditionalAssessment
|
||||
<additional-assessment
|
||||
:questions="assessmentQuestions"
|
||||
:visit-task-id="visitTaskId"
|
||||
@close="additionalAssessmentsDig.visible = false"
|
||||
@@ -275,7 +275,7 @@ import { getAutoCutNextTask } from '@/api/user'
|
||||
import const_ from '@/const/sign-code'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import store from '@/store'
|
||||
// import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import AdditionalAssessment from '@/views/trials/trials-panel/reading/dicoms/components/AdditionalAssessment'
|
||||
@@ -422,7 +422,6 @@ export default {
|
||||
} else {
|
||||
this.expandedRows.push(item.Id)
|
||||
}
|
||||
|
||||
} else {
|
||||
this.expandedRows.push(item.Id)
|
||||
}
|
||||
@@ -441,7 +440,7 @@ export default {
|
||||
} else {
|
||||
filterArr = [3, 4, 5, 6, 2, 8, 10, 7, 1106, 1105]
|
||||
}
|
||||
if ((lesionType === 0 || lesionType === 5) && isLymphNodes === 0 && !this.isShowDetail && (this.criterionType === 1 || this.criterionType === 3 || this.criterionType === 17)) {
|
||||
if ((lesionType === 0 || lesionType === 5) && isLymphNodes === 0 && !this.isShowDetail && (this.criterionType === 1 || this.criterionType === 3 || this.criterionType === 7 || this.criterionType === 17)) {
|
||||
filterArr.push(1)
|
||||
}
|
||||
|
||||
@@ -503,7 +502,7 @@ export default {
|
||||
obj.QuestionName = `${obj.QuestionName} (${item.ReportMark})`
|
||||
}
|
||||
|
||||
if (this.criterionType === 1 || this.criterionType === 3 || this.criterionType === 17) {
|
||||
if (this.criterionType === 1 || this.criterionType === 3 || this.criterionType === 7 || this.criterionType === 17) {
|
||||
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
|
||||
@@ -518,10 +517,10 @@ export default {
|
||||
var liverSegmentIdx = item.Childrens.findIndex(i => i.QuestionMark === 1106)
|
||||
if (liverSegmentIdx > -1) {
|
||||
if (item.Childrens[liverSegmentIdx].Answer.length > 0) {
|
||||
let v = item.Childrens[liverSegmentIdx].Answer[0].Answer
|
||||
const v = item.Childrens[liverSegmentIdx].Answer[0].Answer
|
||||
obj.QuestionName = this.$fd(item.Childrens[liverSegmentIdx].DictionaryCode, parseInt(v))
|
||||
let Answers = {}
|
||||
let mean = item.Childrens.findIndex(i => i.QuestionMark === 1104)
|
||||
const Answers = {}
|
||||
const mean = item.Childrens.findIndex(i => i.QuestionMark === 1104)
|
||||
if (mean > -1) {
|
||||
this.visitTaskList.forEach(v => {
|
||||
const o = item.Childrens[mean].Answer.find(v1 => {
|
||||
@@ -674,7 +673,7 @@ export default {
|
||||
|
||||
this.signVisible = false
|
||||
// window.location.reload()
|
||||
// window.opener.postMessage('refreshTaskList', window.location)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
<div class="dicom-list-container">
|
||||
<div
|
||||
v-for="(series, i) in study.SeriesList"
|
||||
:key="i"
|
||||
:key="series.Id"
|
||||
style="position:relative;margin-top:1px;"
|
||||
@click="activeSeries(series, i, index)"
|
||||
>
|
||||
@@ -65,8 +65,34 @@
|
||||
/>
|
||||
</div>
|
||||
<div class="series-text">
|
||||
<div v-if="series.IsExistMutiFrames && series.InstanceCount > 1"
|
||||
style="position: absolute;right: 0;top: 0;">
|
||||
<el-popover
|
||||
placement="right"
|
||||
trigger="hover"
|
||||
popper-class="instance_frame_wrapper"
|
||||
>
|
||||
<div class="frame_list">
|
||||
<div
|
||||
v-for="(instance, idx) in series.InstanceInfoList"
|
||||
:key="instance.Id"
|
||||
class="frame_content"
|
||||
:style="{'margin-bottom':idx<series.InstanceInfoList.length-1? '5px':'0px'}"
|
||||
@click.stop="showMultiFrames(index,series, i, instance)"
|
||||
>
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;color: #ffeb3b;" />
|
||||
</el-popover>
|
||||
</div>
|
||||
<div v-if="!study.IsCriticalSequence" class="text-desc" :title="series.SeriesNumber">
|
||||
#{{ series.SeriesNumber }}
|
||||
|
||||
</div>
|
||||
<div v-if="series.Description" class="text-desc" :title="series.Description">
|
||||
{{ series.Description }}
|
||||
@@ -80,12 +106,12 @@
|
||||
</span>
|
||||
<span v-show="series.LoadedImageCount >= series.InstanceCount">{{ series.Modality }}: {{ series.InstanceCount }} image</span>
|
||||
</div>
|
||||
<div v-show="series.IsBeMark">
|
||||
<i class="el-icon-star-on" style="font-size: 16px;color: #ff5722;" />
|
||||
<div style="line-height: 12px;">
|
||||
<i v-show="series.IsBeMark || markedSeriesIds.includes(series.Id)" class="el-icon-star-on" style="font-size: 12px;color: #ff5722;" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series.IsDicom && series.LoadedImageProgress>0 && series.LoadedImageProgress<series.InstanceCount * 100" style="width: 100%;">
|
||||
<div v-if="series.LoadedImageCount > 0 && series.LoadedImageCount < series.InstanceCount" style="width: 100%;">
|
||||
<el-progress
|
||||
:percentage="parseInt((series.LoadedImageProgress / series.InstanceCount).toFixed(2))"
|
||||
/>
|
||||
@@ -106,6 +132,12 @@ export default {
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
markedSeriesIds: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -148,6 +180,31 @@ export default {
|
||||
if (!studyId) return
|
||||
this.activeStudy(studyId)
|
||||
},
|
||||
showMultiFrames(studyIndex, series, seriesIndex, instance) {
|
||||
let obj = Object.assign({}, series)
|
||||
this.activeStudyIndex = studyIndex
|
||||
this.activeSeriesIndex = seriesIndex
|
||||
let taskId = this.visitTaskInfo.VisitTaskId
|
||||
const nFrames = instance.NumberOfFrames || 0
|
||||
let imageIds = []
|
||||
const stack = []
|
||||
if (nFrames === 0) {
|
||||
// 单帧
|
||||
stack.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}`)
|
||||
} else {
|
||||
// 多帧
|
||||
for (let i = 0; i < nFrames; i++) {
|
||||
const newImageId = `wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&frame=${i + 1}`
|
||||
stack.push(newImageId)
|
||||
}
|
||||
}
|
||||
imageIds.push(`wadouri:${this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}`)
|
||||
obj.Stack = stack
|
||||
obj.ImageIds = imageIds
|
||||
obj.SliceIndex = 0
|
||||
this.$emit('showMultiFrame', obj)
|
||||
|
||||
},
|
||||
getPreviousOrNextSeries(type, series) {
|
||||
const seriseList = this.studyList.map(s => s.SeriesList).flat()
|
||||
const i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId)
|
||||
@@ -236,6 +293,7 @@ export default {
|
||||
flex: 1;
|
||||
padding-left: 5px;
|
||||
color: #ddd;
|
||||
position: relative;
|
||||
.text-desc {
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
|
||||
</h2>
|
||||
<div>Series: #{{ series.SeriesNumber }}</div>
|
||||
<div>Image: #{{ `${series.SliceIndex + 1}/${series.ImageIds.length}` }}</div>
|
||||
<div v-if="series.Stack">Image: #{{ `${series.SliceIndex + 1}/${series.Stack.length}` }}</div>
|
||||
<div>{{ series.Modality }}</div>
|
||||
</div>
|
||||
<div
|
||||
@@ -60,13 +60,13 @@
|
||||
</div>
|
||||
<div v-if="series" class="left-bottom-text">
|
||||
<div v-show="mousePosition.index.length > 0">
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}
|
||||
</div>
|
||||
<div v-if="(series.Modality === 'CT' || series.Modality === 'DR' || series.Modality === 'CR') && mousePosition.value">
|
||||
HU: {{ mousePosition.value }}
|
||||
</div>
|
||||
<div v-else-if="(series.Modality === 'PT' && mousePosition.value)">
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ?mousePosition.value.toFixed(3) :mousePosition.value.toFixed(digitPlaces) }}
|
||||
{{mousePosition.modalityUnit}}: {{ digitPlaces === -1 ?mousePosition.value.toFixed(3) :mousePosition.value.toFixed(digitPlaces) }}
|
||||
</div>
|
||||
<div v-else-if="mousePosition.value">
|
||||
Density: {{ mousePosition.value }}
|
||||
@@ -74,6 +74,9 @@
|
||||
<div v-show="imageInfo.size">
|
||||
W*H: {{ imageInfo.size }}
|
||||
</div>
|
||||
<div v-show="imageInfo.zoom">
|
||||
Zoom: {{ imageInfo.zoom }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="series" class="right-bottom-text">
|
||||
<div v-show="imageInfo.location">Location: {{ `${Number(imageInfo.location).toFixed(digitPlaces)} mm` }}</div>
|
||||
@@ -110,6 +113,13 @@ import {
|
||||
utilities as csUtils
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'
|
||||
import {
|
||||
utilities as csToolsUtils
|
||||
} from '@cornerstonejs/tools'
|
||||
import { getPTImageIdInstanceMetadata } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/getPTImageIdInstanceMetadata'
|
||||
import ptScalingMetaDataProvider from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/ptScalingMetaDataProvider'
|
||||
import { calculateSUVScalingFactors } from '@cornerstonejs/calculate-suv'
|
||||
import { vec3 } from 'gl-matrix'
|
||||
export default {
|
||||
name: 'ImageViewport',
|
||||
@@ -179,11 +189,14 @@ export default {
|
||||
this.element.oncontextmenu = (e) => e.preventDefault()
|
||||
resizeObserver.observe(this.element)
|
||||
this.element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||
|
||||
// this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||
// this.element.addEventListener('CORNERSTONE_CAMERA_MODIFIED', this.cameraModified)
|
||||
|
||||
this.element.addEventListener('CORNERSTONE_IMAGE_RENDERED', this.imageRendered)
|
||||
this.element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.cornerstoneToolsMouseMove)
|
||||
this.element.addEventListener('mouseleave', () => {
|
||||
this.mousePosition.index = []
|
||||
this.mousePosition.value = null
|
||||
})
|
||||
// console.log(cornerstoneTools)
|
||||
// element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
@@ -191,7 +204,7 @@ export default {
|
||||
stackNewImage(e) {
|
||||
const { detail } = e
|
||||
this.series.SliceIndex = detail.imageIdIndex
|
||||
this.sliderInfo.height = detail.imageIdIndex * 100 / (this.series.ImageIds.length - 1)
|
||||
this.sliderInfo.height = detail.imageIdIndex * 100 / (this.series.Stack.length - 1)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const zoom = viewport.getZoom()
|
||||
@@ -202,6 +215,27 @@ export default {
|
||||
// this.imageInfo.wwwc = `${Math.round(detail.image.windowWidth)}/${Math.round(detail.image.windowCenter)}`
|
||||
this.getOrientationMarker()
|
||||
this.$emit('renderAnnotations', this.series)
|
||||
// const toolGroupId = `viewport-${this.viewportIndex}`
|
||||
// const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||
// toolGroup.setToolEnabled('ScaleOverlay')
|
||||
},
|
||||
imageRendered(e) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const properties = viewport.getProperties()
|
||||
if (properties && properties.voiRange) {
|
||||
var { lower, upper } = properties.voiRange
|
||||
const { windowWidth, windowCenter } = csUtils.windowLevel.toWindowLevel(
|
||||
lower,
|
||||
upper
|
||||
)
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
}
|
||||
const zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
},
|
||||
cameraModified(e) {
|
||||
console.log(e)
|
||||
},
|
||||
voiModified(e) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
@@ -215,6 +249,8 @@ export default {
|
||||
)
|
||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||
}
|
||||
const zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
},
|
||||
getOrientationMarker() {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
@@ -248,7 +284,6 @@ export default {
|
||||
},
|
||||
resetOrientationMarkers() {
|
||||
if (this.originalMarkers.length > 0) {
|
||||
console.log(this.originalMarkers)
|
||||
this.orientationMarkers = [...this.originalMarkers]
|
||||
this.setMarkers()
|
||||
}
|
||||
@@ -284,7 +319,7 @@ export default {
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
if (isPlay) {
|
||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond })
|
||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: false })
|
||||
} else {
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
}
|
||||
@@ -304,7 +339,9 @@ export default {
|
||||
} else if (type === 99999) {
|
||||
newImageIdIndex = numImages - 1
|
||||
}
|
||||
viewport.setImageIdIndex(newImageIdIndex)
|
||||
// viewport.setImageIdIndex(newImageIdIndex)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: newImageIdIndex })
|
||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||
},
|
||||
setZoom(ratio) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
@@ -321,31 +358,108 @@ export default {
|
||||
resize(forceFitToWindow) {
|
||||
console.log('resize: ', forceFitToWindow)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
renderingEngine.resize(true, forceFitToWindow)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
if (!forceFitToWindow) {
|
||||
viewport.setZoom(0.5)
|
||||
viewport.render()
|
||||
} else {
|
||||
viewport.setZoom(1)
|
||||
viewport.render()
|
||||
}
|
||||
},
|
||||
async prefetchMetadataInformation(imageIdsToPrefetch, modality) {
|
||||
let taskPromises = []
|
||||
for (let i = 0; i < imageIdsToPrefetch.length; i++) {
|
||||
taskPromises.push(cornerstoneDICOMImageLoader.wadouri.loadImage(imageIdsToPrefetch[i]).promise)
|
||||
if (taskPromises.length >= 6 || i === imageIdsToPrefetch.length - 1) {
|
||||
let res = await Promise.all(taskPromises)
|
||||
if (modality === 'PT') {
|
||||
this.cachePTMetadata(res)
|
||||
}
|
||||
taskPromises = []
|
||||
}
|
||||
}
|
||||
},
|
||||
cachePTMetadata(images) {
|
||||
images.map(i=>{
|
||||
const instanceMetadata = getPTImageIdInstanceMetadata(i.imageId)
|
||||
if (typeof instanceMetadata.CorrectedImage === 'string') {
|
||||
instanceMetadata.CorrectedImage = instanceMetadata.CorrectedImage.split('\\')
|
||||
}
|
||||
if (instanceMetadata) {
|
||||
const suvScalingFactors = calculateSUVScalingFactors([instanceMetadata])
|
||||
ptScalingMetaDataProvider.addInstance(i.imageId, suvScalingFactors[0])
|
||||
}
|
||||
})
|
||||
},
|
||||
async setSeriesInfo(obj, isLocate = false) {
|
||||
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) {
|
||||
obj.SliceIndex = this.series.SliceIndex
|
||||
try {
|
||||
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) {
|
||||
obj.SliceIndex = this.series.SliceIndex
|
||||
}
|
||||
// if (isLocate && obj.SliceIndex === this.series.SliceIndex) return
|
||||
if (this.series?.Stack && obj.Stack[obj.SliceIndex] === this.series.Stack[this.series.SliceIndex]) return
|
||||
this.series = { ...obj }
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const image = await cornerstoneDICOMImageLoader.wadouri.loadImage(obj.ImageIds[obj.SliceIndex]).promise
|
||||
if (obj.Modality === 'PT') {
|
||||
this.cachePTMetadata([image])
|
||||
}
|
||||
this.prefetchMetadataInformation(obj.ImageIds, obj.Modality)
|
||||
await viewport.setStack(this.series.Stack, obj.SliceIndex)
|
||||
viewport.render()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
this.series = { ...obj }
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
await viewport.setStack(obj.ImageIds, obj.SliceIndex)
|
||||
cornerstoneTools.utilities.stackPrefetch.enable(viewport.element)
|
||||
viewport.render()
|
||||
},
|
||||
cornerstoneToolsMouseMove(e) {
|
||||
const { currentPoints } = e.detail
|
||||
const worldPoint = currentPoints.world
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const imageData = viewport.getImageData()
|
||||
if (!imageData) return
|
||||
const index = imageData.imageData.worldToIndex(worldPoint)
|
||||
let referencedImageId = viewport.getCurrentImageId()
|
||||
const data = viewport.getImageData()
|
||||
if (!data) return
|
||||
const { dimensions, imageData, metadata, voxelManager } = data
|
||||
const index = imageData.worldToIndex(worldPoint)
|
||||
index[0] = Math.floor(index[0])
|
||||
index[1] = Math.floor(index[1])
|
||||
index[2] = Math.floor(index[2])
|
||||
this.mousePosition.index = index
|
||||
const modality = metadata.Modality
|
||||
let ijk = csUtils.transformWorldToIndex(imageData, worldPoint)
|
||||
ijk = vec3.round(ijk, ijk);
|
||||
if (csUtils.indexWithinDimensions(ijk, dimensions)) {
|
||||
this.isHandleOutsideImage = false
|
||||
let value = voxelManager.getAtIJKPoint(ijk)
|
||||
ijk[2] = viewport.getCurrentImageIdIndex()
|
||||
let modalityUnit
|
||||
if (modality === 'US') {
|
||||
const calibratedResults = csToolsUtils.getCalibratedProbeUnitsAndValue(image, [ijk])
|
||||
const hasEnhancedRegionValues = calibratedResults.values.every(
|
||||
(value) => value !== null
|
||||
)
|
||||
value = (hasEnhancedRegionValues ? calibratedResults.values : value)
|
||||
modalityUnit = hasEnhancedRegionValues
|
||||
? calibratedResults.units
|
||||
: 'raw';
|
||||
} else {
|
||||
const scalingModule = referencedImageId && metaData.get('scalingModule', referencedImageId)
|
||||
const isSuvScaled = typeof scalingModule?.suvbw === 'number'
|
||||
const pixelUnitsOptions = {
|
||||
isPreScaled: csToolsUtils.viewport.isViewportPreScaled(viewport, referencedImageId),
|
||||
isSuvScaled: isSuvScaled,
|
||||
}
|
||||
modalityUnit = csToolsUtils.getPixelValueUnits(
|
||||
modality,
|
||||
referencedImageId,
|
||||
pixelUnitsOptions
|
||||
);
|
||||
}
|
||||
this.mousePosition.value = value
|
||||
this.mousePosition.modalityUnit = modalityUnit
|
||||
}
|
||||
},
|
||||
toggleTask(evt, visitTaskNum, i) {
|
||||
this.$emit('activeViewport', this.viewportIndex)
|
||||
@@ -367,13 +481,14 @@ export default {
|
||||
clickSlider(e) {
|
||||
const height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
|
||||
this.sliderInfo.height = height
|
||||
let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
let sliceIdx = Math.trunc(this.series.Stack.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(sliceIdx)
|
||||
// viewport.setImageIdIndex(sliceIdx)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseup(e) {
|
||||
@@ -395,14 +510,15 @@ export default {
|
||||
if (delta < 0) return
|
||||
if (delta > boxHeight) return
|
||||
const height = delta * 100 / boxHeight
|
||||
let sliceIdx = Math.trunc(this.series.ImageIds.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.ImageIds.length ? this.series.ImageIds.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
let sliceIdx = Math.trunc(this.series.Stack.length * height / 100)
|
||||
sliceIdx = sliceIdx >= this.series.Stack.length ? this.series.Stack.length - 1 : sliceIdx < 0 ? 0 : sliceIdx
|
||||
this.sliderInfo.height = height
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(
|
||||
this.viewportId
|
||||
)
|
||||
viewport.setImageIdIndex(sliceIdx)
|
||||
// viewport.setImageIdIndex(sliceIdx)
|
||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIdx })
|
||||
viewport.render()
|
||||
},
|
||||
sliderMouseleave(e) {
|
||||
|
||||
@@ -1,16 +1,9 @@
|
||||
<template>
|
||||
<div class="visit-review-container">
|
||||
<el-tabs
|
||||
v-model="activeName"
|
||||
>
|
||||
<el-tabs v-model="activeName">
|
||||
<!-- 阅片 -->
|
||||
<el-tab-pane
|
||||
v-if="taskInfo"
|
||||
ref="readPage"
|
||||
:label="$t('trials:reading:tabTitle:review')"
|
||||
name="read"
|
||||
>
|
||||
<read-page />
|
||||
<el-tab-pane v-if="taskInfo" :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||
<read-page ref="readPage" :reading-tool="readingTool" />
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane
|
||||
@@ -18,8 +11,12 @@
|
||||
:label="$t('trials:reading:tabTitle:report')"
|
||||
name="report"
|
||||
>
|
||||
<report-page
|
||||
v-if="activeName === 'report'"
|
||||
<report-page
|
||||
v-if="activeName === 'report' && taskInfo.CriterionType !== 0"
|
||||
@setReadingTaskState="setReadingTaskState"
|
||||
/>
|
||||
<customize-report-page
|
||||
v-if="activeName === 'report' && taskInfo.CriterionType === 0"
|
||||
@setReadingTaskState="setReadingTaskState"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
@@ -29,11 +26,19 @@
|
||||
<script>
|
||||
import ReadPage from './ReadPage'
|
||||
import ReportPage from './ReportPage'
|
||||
import CustomizeReportPage from './customize/ReportPage'
|
||||
export default {
|
||||
name: 'VisitReview',
|
||||
components: {
|
||||
ReadPage,
|
||||
ReportPage
|
||||
ReportPage,
|
||||
CustomizeReportPage
|
||||
},
|
||||
props: {
|
||||
readingTool: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -42,6 +47,7 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
console.log(this.readingTool)
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
},
|
||||
methods: {
|
||||
@@ -52,37 +58,44 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.visit-review-container {
|
||||
height: 100vh;
|
||||
.visit-review-container {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #000;
|
||||
padding: 5px;
|
||||
|
||||
::v-deep .el-tabs {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-color: #000;
|
||||
padding: 5px;
|
||||
::v-deep .el-tabs {
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
.el-tabs__item {
|
||||
color: #fff;
|
||||
}
|
||||
.el-tabs__item.is-active {
|
||||
color: #428bca;
|
||||
}
|
||||
.el-tabs__item:hover {
|
||||
color: #428bca;
|
||||
}
|
||||
.el-tabs__header {
|
||||
height: 50px;
|
||||
margin:0px;
|
||||
}
|
||||
.el-tabs__content {
|
||||
flex: 1;
|
||||
margin:0px;
|
||||
}
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.el-tabs__item {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.el-tabs__item.is-active {
|
||||
color: #428bca;
|
||||
}
|
||||
|
||||
.el-tabs__item:hover {
|
||||
color: #428bca;
|
||||
}
|
||||
|
||||
.el-tabs__header {
|
||||
height: 50px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.el-tabs__content {
|
||||
flex: 1;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -0,0 +1,325 @@
|
||||
<template>
|
||||
<div class="colorMap">
|
||||
<div class="item" effect="dark" :title="$t('trials:lugano:button:colormap')">
|
||||
<div class="colorBar"
|
||||
style="display:flex;justify-content: flex-start;align-items: center;position: relative;"
|
||||
@mouseleave="isSlideMoving = false">
|
||||
<div class="tool-wrapper" style="margin-right:0px" @click.stop="showColorBarPanel($event)"
|
||||
@mouseleave="handleColorBarMouseout">
|
||||
<div>
|
||||
<div class="dropdown">
|
||||
<div id="colorBar" class="icon" style="display: flex;align-items: center;width:266px">
|
||||
<canvas id="colorBarCanvas" />
|
||||
|
||||
</div>
|
||||
<!-- 伪彩 -->
|
||||
<div class="text">{{ $t('trials:lugano:button:colormap') }}</div>
|
||||
<div class="dropdown-content" style="width:266px">
|
||||
<ul>
|
||||
<li v-for="(colorMap, index) in colorMaps" :key="colorMap"
|
||||
style="display: flex;align-items: center;margin-bottom:5px;padding:0 5px;justify-content: space-between;"
|
||||
:class="{ activeLi: rgbPresetName === colorMap }"
|
||||
@click="setColorMap(colorMap)">
|
||||
<canvas :id="`colorBarCanvas${index}`" />
|
||||
<span style="margin-left:5px;font-size: 10px;">{{ colorMap
|
||||
}}</span>
|
||||
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="margin-left:-1px;border: 1px solid #424242;">
|
||||
<el-input v-model="range" size="mini" style="width:120px" maxlength="3"
|
||||
oninput="if(value){value=value.replace(/[^\d]/g,'')} if(value<=0){value=''}"
|
||||
@change="upperRangeChange">
|
||||
<template slot="append">g/ml</template>
|
||||
</el-input>
|
||||
</div>
|
||||
<div id="slider" style="position: absolute;left: 6px;top:5px;cursor: pointer;">
|
||||
<div id="sliderBox" class="slider" style="height: 17px;width: 10px;background-color: #909399;" />
|
||||
<div id="slider-position" style="color:#ddd;font-size: 12px;">0</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
utilities as csUtils,
|
||||
} from '@cornerstonejs/core'
|
||||
import colormaps from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/colormaps'
|
||||
import vtkColorMaps from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction/ColorMaps'
|
||||
const { registerColormap, getColormapNames, getColormap } = csUtils.colormap
|
||||
export default {
|
||||
name: "colorMap",
|
||||
data() {
|
||||
return {
|
||||
colorMaps: [],
|
||||
rgbPresetName: 'siemens',
|
||||
range: 40,
|
||||
upper: 6,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
colormaps.forEach(colormap => {
|
||||
registerColormap(colormap)
|
||||
})
|
||||
this.colorMaps = getColormapNames()
|
||||
this.colorMaps.unshift('hsv')
|
||||
this.$nextTick(() => {
|
||||
this.renderColorMaps()
|
||||
this.upperRangeChange(this.range)
|
||||
this.initSlider()
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
renderColorMaps() {
|
||||
this.createColorBar(this.rgbPresetName, 'colorBarCanvas', 256, 15)
|
||||
this.colorMaps.forEach((e, index) => {
|
||||
this.createColorBar(e, `colorBarCanvas${index}`, 180, 15)
|
||||
})
|
||||
},
|
||||
voiChange(v) {
|
||||
this.$emit('voiChange', v)
|
||||
},
|
||||
initSlider() {
|
||||
var slider = document.getElementById('slider')
|
||||
var sliderBox = document.getElementById('sliderBox')
|
||||
var container = document.getElementById('colorBarCanvas')
|
||||
slider.addEventListener('mousedown', () => {
|
||||
this.isSlideMoving = true
|
||||
})
|
||||
document.addEventListener('mousemove', (e) => {
|
||||
if (this.isSlideMoving) {
|
||||
var containerWidth = container.clientWidth
|
||||
var sliderWidth = sliderBox.clientWidth
|
||||
var maxLeft = containerWidth - sliderWidth
|
||||
var left = e.clientX - container.getBoundingClientRect().left
|
||||
var position = null
|
||||
position = left
|
||||
if (left < 0) {
|
||||
left = 6
|
||||
position = 0
|
||||
} else if (left > maxLeft) {
|
||||
left = maxLeft + 6
|
||||
position = maxLeft
|
||||
}
|
||||
|
||||
slider.style.left = left + 'px'
|
||||
var positionValue = document.getElementById('slider-position')
|
||||
var upper = this.range
|
||||
position = parseInt((position / maxLeft) * upper)
|
||||
positionValue.textContent = position
|
||||
this.upper = position
|
||||
this.voiChange(position)
|
||||
}
|
||||
})
|
||||
document.addEventListener('mouseup', () => {
|
||||
this.isSlideMoving = false
|
||||
})
|
||||
},
|
||||
upperRangeChange(v) {
|
||||
if (v === 0 || v < this.upper) {
|
||||
return
|
||||
}
|
||||
var sliderBox = document.getElementById('sliderBox')
|
||||
var container = document.getElementById('colorBarCanvas')
|
||||
var containerWidth = container.clientWidth
|
||||
var sliderWidth = sliderBox.clientWidth
|
||||
var maxLeft = containerWidth - sliderWidth
|
||||
var left = (this.upper / this.range) * maxLeft
|
||||
if (left < 0) {
|
||||
left = 6
|
||||
} else if (left >= maxLeft) {
|
||||
left = maxLeft + 6
|
||||
}
|
||||
var slider = document.getElementById('slider')
|
||||
slider.style.left = left + 'px'
|
||||
var positionValue = document.getElementById('slider-position')
|
||||
positionValue.textContent = this.upper
|
||||
},
|
||||
createColorBar(rgbPresetName, elId, width, height) {
|
||||
var colorMap = null
|
||||
if (rgbPresetName === 'hsv') {
|
||||
colorMap = vtkColorMaps.getPresetByName(rgbPresetName)
|
||||
} else {
|
||||
colorMap = getColormap(rgbPresetName)
|
||||
}
|
||||
|
||||
const rgbPoints = colorMap.RGBPoints
|
||||
const canvas = document.getElementById(elId)
|
||||
const ctx = canvas.getContext('2d')
|
||||
const canvasWidth = width
|
||||
const canvasHeight = height
|
||||
const rectWidth = width
|
||||
const rectHeight = canvasHeight
|
||||
canvas.width = canvasWidth
|
||||
canvas.height = canvasHeight
|
||||
const gradient = ctx.createLinearGradient(0, 0, rectWidth, 0)
|
||||
for (let i = 0; i < rgbPoints.length; i += 4) {
|
||||
let position = 0
|
||||
if (rgbPoints[0] === -1) {
|
||||
position = (rgbPoints[i] + 1) / 2
|
||||
} else {
|
||||
position = rgbPoints[i]
|
||||
}
|
||||
const color = `rgb(${parseInt(rgbPoints[i + 1] * 255)}, ${parseInt(rgbPoints[i + 2] * 255)}, ${parseInt(rgbPoints[i + 3] * 255)})`
|
||||
gradient.addColorStop(position, color)
|
||||
}
|
||||
ctx.fillStyle = gradient
|
||||
ctx.fillRect(0, 0, rectWidth, rectHeight)
|
||||
},
|
||||
async setColorMap(rgbPresetName) {
|
||||
this.rgbPresetName = rgbPresetName
|
||||
this.createColorBar(this.rgbPresetName, 'colorBarCanvas', 256, 15)
|
||||
this.$emit("setColorMap", rgbPresetName)
|
||||
},
|
||||
showColorBarPanel(e) {
|
||||
e.currentTarget.firstChild.firstChild.lastChild.style.display = 'block'
|
||||
},
|
||||
handleColorBarMouseout(e) {
|
||||
e.currentTarget.firstChild.firstChild.lastChild.style.display = 'none'
|
||||
},
|
||||
init() {
|
||||
this.createColorBar(this.rgbPresetName, 'colorBarCanvas', 256, 15)
|
||||
this.$emit("setColorMap", this.rgbPresetName)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.activeLi {
|
||||
background-color: #919295;
|
||||
}
|
||||
|
||||
.tool-wrapper {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin-right: 30px;
|
||||
|
||||
.icon {
|
||||
padding: 5px;
|
||||
border: 1px solid #404040;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
.svg-icon {
|
||||
font-size: 25px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.text {
|
||||
position: relative;
|
||||
font-size: 12px;
|
||||
margin-top: 5px;
|
||||
color: #d0d0d0;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.dropdown {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
|
||||
.icon-content {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
border: 1px solid #404040;
|
||||
}
|
||||
|
||||
.text {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.tool-icon {
|
||||
padding: 5px;
|
||||
cursor: pointer;
|
||||
text-align: center;
|
||||
|
||||
.svg-icon {
|
||||
font-size: 20px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
.arrow-icon {
|
||||
cursor: pointer;
|
||||
padding: 7px 2px 7px 0px;
|
||||
}
|
||||
|
||||
.arrow-icon:hover {
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.icon-content-d:hover {
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.tool-icon-d {
|
||||
padding: 5px;
|
||||
|
||||
.svg-icon {
|
||||
font-size: 20px;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
background-color: #383838;
|
||||
color: #fff;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0, 0, 0, 0.2);
|
||||
z-index: 9999;
|
||||
font-size: 12px;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
text-align: center;
|
||||
|
||||
li {
|
||||
a {
|
||||
display: block;
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ul li:hover {
|
||||
background-color: #727272;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
border: 1px solid rgba(255, 255, 255, 0.21);
|
||||
position: relative;
|
||||
|
||||
&_active {
|
||||
// border: 2px solid #ffeb3b;fff
|
||||
border: 1px dashed rgb(250, 250, 0);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.colorBar {
|
||||
::v-deep .el-input--mini .el-input__inner {
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
border: none;
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,438 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="questionList-wrapper">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo">
|
||||
<span v-if="visitInfo.SubjectCode">{{ visitInfo.SubjectCode }} </span>
|
||||
<span style="margin-left:5px;">{{ visitInfo.TaskBlindName }}</span>
|
||||
</h3>
|
||||
<div v-if="readingTaskState < 2">
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
|
||||
<i
|
||||
class="el-icon-refresh-left"
|
||||
@click="resetForm"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<el-form
|
||||
v-if="taskInfo && rerender"
|
||||
ref="questions"
|
||||
size="small"
|
||||
:model="questionForm"
|
||||
class="ecrf-form"
|
||||
>
|
||||
<template v-if="rerender">
|
||||
<QuestionFormItem
|
||||
v-for="question of questions"
|
||||
:key="question.Id"
|
||||
:visit-task-id="visitTaskId"
|
||||
:question="question"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
:criterion-id="criterionId"
|
||||
:calculation-list="calculationList"
|
||||
:is-baseline="isBaseLineTask"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
@setFormItemData="setFormItemData"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<el-form-item v-if="readingTaskState < 2">
|
||||
<div style="text-align:center;">
|
||||
<el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" type="primary" @click="skipTask">
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
<el-button v-if="taskInfo && taskInfo.IseCRFShowInDicomReading" type="primary" @click="handleSubmit">
|
||||
{{ $t('common:button:submit') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
|
||||
<!-- 签名框 -->
|
||||
<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 { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
|
||||
import { setSkipReadingCache, resetReadingTask } from '@/api/reading'
|
||||
import const_ from '@/const/sign-code'
|
||||
import QuestionFormItem from '@/views/trials/trials-panel/reading/dicoms/customize/CustomizeQuestionFormItem'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
export default {
|
||||
name: 'EcrfList',
|
||||
components: {
|
||||
QuestionFormItem,
|
||||
SignForm
|
||||
},
|
||||
props: {
|
||||
visitInfo: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
trialId: '',
|
||||
criterionId: '',
|
||||
visitTaskId: '',
|
||||
loading: false,
|
||||
questions: [],
|
||||
questionForm: {},
|
||||
publicQuestions: [],
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
activeName: 0,
|
||||
classArr: [],
|
||||
calculationList: [],
|
||||
taskInfo: null,
|
||||
isBaseLineTask: false,
|
||||
rerender: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.visitTaskId = this.visitInfo.VisitTaskId
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
this.isBaseLineTask = this.taskInfo.IsBaseLine
|
||||
this.criterionType = this.taskInfo.CriterionType
|
||||
this.getQuestionCalculateRelation()
|
||||
this.getQuestions()
|
||||
},
|
||||
methods: {
|
||||
async getQuestions() {
|
||||
this.loading = true
|
||||
try {
|
||||
const param = {
|
||||
visitTaskId: this.visitTaskId
|
||||
}
|
||||
const res = await getCustomTableQuestionAnswer(param)
|
||||
if (res.IsSuccess) {
|
||||
// this.readingTaskState = res.OtherInfo.ReadingTaskState
|
||||
res.Result.SinglePage.map((v) => {
|
||||
if (v.Type === 'group' && v.Childrens.length === 0) return
|
||||
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
|
||||
this.$set(this.questionForm, v.Id, v.Answer)
|
||||
}
|
||||
if (v.Type === 'table' || v.Type === 'basicTable') {
|
||||
this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
|
||||
}
|
||||
if (v.Type === 'class') {
|
||||
this.classArr.push({ triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType })
|
||||
}
|
||||
if (v.Type === 'number') {
|
||||
this.$set(this.questionForm, v.Id, v.Answer === '' ? '' : parseFloat(v.Answer).toFixed(this.digitPlaces))
|
||||
}
|
||||
if (v.Childrens.length > 0) {
|
||||
this.setChild(v.Childrens)
|
||||
}
|
||||
})
|
||||
this.questions = res.Result.SinglePage
|
||||
this.loading = false
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
setChild(obj) {
|
||||
obj.forEach(i => {
|
||||
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
|
||||
this.$set(this.questionForm, i.Id, i.Answer)
|
||||
}
|
||||
if (i.Type === 'table' || i.Type === 'basicTable') {
|
||||
i.TableQuestions.Questions.forEach(o => {
|
||||
if (o.Type === 'number') {
|
||||
i.TableQuestions.Answers.forEach((ite, index) => {
|
||||
this.$set(i.TableQuestions.Answers[index], o.Id, i.TableQuestions.Answers[index][o.Id] ? parseFloat(i.TableQuestions.Answers[index][o.Id]).toFixed(this.digitPlaces) : null)
|
||||
})
|
||||
}
|
||||
})
|
||||
this.$set(this.questionForm, i.Id, i.TableQuestions.Answers)
|
||||
}
|
||||
if (i.Type === 'class') {
|
||||
this.classArr.push({ triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType })
|
||||
}
|
||||
if (i.Type === 'number') {
|
||||
this.$set(this.questionForm, i.Id, i.Answer === '' ? '' : parseFloat(i.Answer).toFixed(this.digitPlaces))
|
||||
}
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.setChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
async getQuestionCalculateRelation() {
|
||||
try {
|
||||
const res = await getQuestionCalculateRelation({ TrialReadingCriterionId: this.criterionId })
|
||||
this.calculationList = res.Result
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
async handleSave(isMsg) {
|
||||
const valid = await this.$refs['questions'].validate()
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
try {
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
if (this.questionForm[k] instanceof Array) {} else {
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
}
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
answers: answers
|
||||
}
|
||||
const res = await changeDicomReadingQuestionAnswer(params)
|
||||
if (res.IsSuccess) {
|
||||
if (isMsg) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.loading = false
|
||||
}
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async handleSubmit() {
|
||||
const valid = await this.$refs['questions'].validate()
|
||||
if (!valid) return
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
async signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
answers.push({ readingQuestionTrialId: k, answer: this.questionForm[k] })
|
||||
}
|
||||
var params = {
|
||||
data: {
|
||||
trialId: this.trialId,
|
||||
visitTaskId: this.visitTaskId,
|
||||
readingQuestionCriterionTrialId: this.criterionId,
|
||||
answerList: answers
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
try {
|
||||
const res = await submitVisitTaskQuestionsInDto(params)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.isEdit = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
this.signVisible = false
|
||||
this.$emit('setReadingTaskState', 2)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:noneDicoms:message:msg1'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
window.location.reload()
|
||||
}
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.questionForm[v] = null
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
|
||||
this.classArr.map(i => {
|
||||
if (i.triggerId === obj.key) {
|
||||
let answer = null
|
||||
const list = JSON.parse(i.classifyAlgorithms)
|
||||
if (i.classifyType === 0) {
|
||||
const o = list.find(v => {
|
||||
return (
|
||||
parseFloat(obj.val) >= parseFloat(v.gt) &&
|
||||
parseFloat(obj.val) < parseFloat(v.lt)
|
||||
)
|
||||
})
|
||||
answer = o ? o.label : null
|
||||
} else if (i.classifyType === 1) {
|
||||
const o = list.find(v => {
|
||||
return v.val.includes(obj.val)
|
||||
})
|
||||
answer = o ? o.label : null
|
||||
}
|
||||
this.$set(this.questionForm, i.classId, answer)
|
||||
}
|
||||
})
|
||||
},
|
||||
async resetForm() {
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:dicomReading:message:confirmReset1'),
|
||||
this.$t('trials:dicomReading:message:confirmReset2'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
|
||||
if (res.IsSuccess) {
|
||||
this.rerender = false
|
||||
await this.getQuestionCalculateRelation()
|
||||
await this.getQuestions()
|
||||
this.$emit('resetAnnotations', this.visitTaskId)
|
||||
this.$nextTick(()=>{
|
||||
this.rerender = true
|
||||
})
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.questionList-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.container{
|
||||
padding: 10px;
|
||||
.basic-info{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
h3{
|
||||
color: #ddd;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
i{
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
.ecrf-form{
|
||||
::v-deep .el-form-item__label{
|
||||
color: #ddd;
|
||||
}
|
||||
}
|
||||
::v-deep .el-table,
|
||||
.el-table__expanded-cell {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
|
||||
::v-deep .el-table th,
|
||||
.el-table tr {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
::v-deep .el-table__body tr > td {
|
||||
background-color: #000 !important;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
::v-deep .el-table__body tr:hover > td {
|
||||
background-color: #858282 !important;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
::v-deep .el-table--border th.gutter:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
::v-deep .el-dialog{
|
||||
background: #1e1e1e;
|
||||
border: 1px solid #ddd;
|
||||
color: #ddd;
|
||||
.el-dialog__title{
|
||||
color:#fff;
|
||||
}
|
||||
.el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
.el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
.el-form-item__label{
|
||||
color: #dfdfdf
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// .ecrf-list-container{
|
||||
// min-height:400px;
|
||||
// color: #ddd;
|
||||
|
||||
// }
|
||||
</style>
|
||||
@@ -0,0 +1,855 @@
|
||||
<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-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
|
||||
v-if="taskQuestions.length > 0"
|
||||
ref="reportList"
|
||||
v-adaptive="{bottomOffset:0}"
|
||||
:data="taskQuestions"
|
||||
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" />
|
||||
</el-button>
|
||||
</div>
|
||||
</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')">
|
||||
<!-- 输入框 -->
|
||||
<div>
|
||||
<template v-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)" />
|
||||
<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"
|
||||
size="mini"
|
||||
@blur="limitBlur(questionForm[scope.row.QuestionId][scope.row.xfIndex], scope.row.TableQuestionId, scope.row.ValueType)"
|
||||
@focus="() => {questionId = scope.row.QuestionId}"
|
||||
>
|
||||
<template v-if="scope.row.Unit !== 0" slot="append">{{ scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit }}</template>
|
||||
<template v-else-if="scope.row.ValueType === 2" slot="append">%</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"
|
||||
size="mini"
|
||||
@blur="limitBlur(questionForm, scope.row.QuestionId, scope.row.ValueType)"
|
||||
@focus="() => {questionId = scope.row.QuestionId}"
|
||||
>
|
||||
<template v-if="scope.row.Unit !== 0" slot="append">{{ scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit }}</template>
|
||||
<template v-else-if="scope.row.ValueType === 2" slot="append">%</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 v-else-if="scope.row.Type==='upload' && scope.row.Answers[task.VisitTaskId]">
|
||||
<span v-for="(url,index) in scope.row.Answers[task.VisitTaskId].split('|')" :key="url" style="margin-left: 5px;">
|
||||
<el-button v-if="scope.row.Answers[task.VisitTaskId]" type="text" @click="preview(url)">
|
||||
{{ `${$t('trials:noneDicom:title:attachment')}${index + 1}` }}
|
||||
</el-button>
|
||||
</span>
|
||||
</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 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>
|
||||
|
||||
<!-- 预览文件 -->
|
||||
<el-dialog
|
||||
v-if="previewVisible"
|
||||
:visible.sync="previewVisible"
|
||||
:title="$t('common:button:preview')"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div
|
||||
class="base-modal-body"
|
||||
style="border: 2px solid #ccc; padding: 10px"
|
||||
>
|
||||
<PreviewFile
|
||||
v-if="previewVisible"
|
||||
:file-path="currentPath"
|
||||
:file-type="currentType"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import { getAutoCutNextTask } from '@/api/user'
|
||||
import const_ from '@/const/sign-code'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import PreviewFile from '@/components/PreviewFile/index'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import store from '@/store'
|
||||
export default {
|
||||
name: 'CustomizeReportPage',
|
||||
components: { SignForm, PreviewFile },
|
||||
data() {
|
||||
return {
|
||||
trialId: '',
|
||||
visitTaskId: '',
|
||||
subjectId: '',
|
||||
readingTool: 1,
|
||||
criterionType: null,
|
||||
isReadingTaskViewInOrder: false,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
visitTaskList: [],
|
||||
taskQuestions: [],
|
||||
loading: false,
|
||||
answers: [],
|
||||
readingTaskState: 2,
|
||||
answerArr: [],
|
||||
questions: [],
|
||||
CalculationList: [],
|
||||
TrialReadingCriterionId: null,
|
||||
tableAnswers: {},
|
||||
questionForm: {},
|
||||
questionId: null,
|
||||
taskInfo: null,
|
||||
previewVisible: false,
|
||||
currentPath: '',
|
||||
currentType: ''
|
||||
}
|
||||
},
|
||||
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)
|
||||
}
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.visitTaskId = this.taskInfo.VisitTaskId
|
||||
this.subjectId = this.taskInfo.SubjectId
|
||||
this.criterionType = this.taskInfo.CriterionType
|
||||
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.TrialReadingCriterionId = this.taskInfo.TrialReadingCriterionId
|
||||
window.addEventListener('resize', () => {
|
||||
this.handleResize()
|
||||
})
|
||||
await this.getQuestionCalculateRelation()
|
||||
this.getReportInfo()
|
||||
},
|
||||
methods: {
|
||||
limitBlur(questionForm, id, valueType) {
|
||||
const value = questionForm[id]
|
||||
if (valueType === 0) {
|
||||
this.$set(questionForm, id, parseInt(value))
|
||||
} else if (valueType === 3) {
|
||||
this.$set(questionForm, id, parseFloat(value))
|
||||
} else {
|
||||
this.$set(questionForm, id, parseFloat(value).toFixed(this.digitPlaces))
|
||||
}
|
||||
},
|
||||
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) {
|
||||
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' && v.Type !== 'basicTable') return
|
||||
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
|
||||
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId])
|
||||
}
|
||||
if (v.Type === 'table' || v.Type === 'basicTable') {
|
||||
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') {
|
||||
let val = null
|
||||
if (v.ValueType === 0) {
|
||||
val = parseInt(v.Answers[this.visitTaskId])
|
||||
} else if (v.ValueType === 3) {
|
||||
val = v.Answers[this.visitTaskId]
|
||||
} else {
|
||||
val = v.Answers[this.visitTaskId] === '' ? null : v.Answers[this.visitTaskId]
|
||||
}
|
||||
this.$set(this.questionForm, v.QuestionId, val)
|
||||
}
|
||||
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' && i.Type !== 'basicTable') {
|
||||
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId])
|
||||
}
|
||||
if (i.Type === 'table' || i.Type === 'basicTable') {
|
||||
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
|
||||
this.$set(this.questionForm, i.QuestionId, tableAnswers)
|
||||
}
|
||||
if (i.Type === 'number') {
|
||||
let val = null
|
||||
if (i.ValueType === 0) {
|
||||
val = parseInt(i.Answers[this.visitTaskId])
|
||||
} else if (i.ValueType === 3) {
|
||||
val = i.Answers[this.visitTaskId]
|
||||
} else {
|
||||
val = i.Answers[this.visitTaskId] === '' ? null : i.Answers[this.visitTaskId]
|
||||
}
|
||||
this.$set(this.questionForm, i.QuestionId, val)
|
||||
}
|
||||
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table' && i.Type !== 'basicTable') {
|
||||
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:
|
||||
const arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.max(...arr)
|
||||
break
|
||||
case 9:
|
||||
const arr1 = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr1.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr1.length === 0 ? 0 : Math.min(...arr1)
|
||||
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)
|
||||
}
|
||||
if (rules.ValueType === 2) {
|
||||
num = num * 100
|
||||
}
|
||||
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(this.digitPlaces) : '∞'
|
||||
},
|
||||
getReportInfo() {
|
||||
this.loading = true
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.trialId
|
||||
}
|
||||
this.taskQuestions = []
|
||||
getReadingReportEvaluation(params).then(res => {
|
||||
this.readingTaskState = res.Result.ReadingTaskState
|
||||
this.answerArr = []
|
||||
this.questions = res.Result.TaskQuestions.concat()
|
||||
var taskQuestions = this.getQuestions(res.Result.TaskQuestions)
|
||||
taskQuestions.forEach(item => {
|
||||
this.$set(this.taskQuestions, this.taskQuestions.length, item)
|
||||
})
|
||||
this.visitTaskList = res.Result.VisitTaskList
|
||||
this.InitVisitTaskQuestionForm()
|
||||
this.handleResize()
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
getQuestions(questions) {
|
||||
const arr = []
|
||||
if (questions.length !== 0) {
|
||||
questions.forEach((item) => {
|
||||
const obj = item
|
||||
this.$set(obj, 'Answers', {})
|
||||
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') {
|
||||
let val = null
|
||||
if (item.ValueType === 0) {
|
||||
val = parseInt(i.Answer)
|
||||
} else if (item.ValueType === 3) {
|
||||
val = i.Answer
|
||||
} else {
|
||||
val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(this.digitPlaces)
|
||||
}
|
||||
this.$set(obj.Answers, i.VisitTaskId, val)
|
||||
} 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)
|
||||
}
|
||||
arr.push(obj)
|
||||
})
|
||||
}
|
||||
return arr
|
||||
},
|
||||
handleShowDetail(val) {
|
||||
this.getReportInfo()
|
||||
// this.taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null)
|
||||
},
|
||||
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 ? this.$refs.reportList.doLayout() : ''
|
||||
})
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
async signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
try {
|
||||
var params = {
|
||||
data: {
|
||||
visitTaskId: this.visitTaskId
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
const res = await submitDicomVisitTask(params)
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
if (this.$refs['signForm']) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
|
||||
this.signVisible = false
|
||||
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
this.$emit('setReadingTaskState', 2)
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
const res = await getAutoCutNextTask()
|
||||
const isAutoTask = res.Result.AutoCutNextTask
|
||||
if (isAutoTask) {
|
||||
window.location.reload()
|
||||
} else {
|
||||
// '当前阅片任务已完成,是否进入下一个阅片任务?'
|
||||
this.$confirm(this.$t('trials:readingReport:message:msg4'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
.catch(action => {
|
||||
// changeURLStatic('visitTaskId', this.visitTaskId)
|
||||
})
|
||||
}
|
||||
}
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
previewDicoms(task) {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close()
|
||||
}
|
||||
var token = getToken()
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
// var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
var subjectCode = localStorage.getItem('subjectCode')
|
||||
var subjectId = this.$router.currentRoute.query.subjectId
|
||||
var trialId = this.$router.currentRoute.query.trialId
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
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 })
|
||||
this.openWindow = 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] })
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
},
|
||||
// 预览
|
||||
preview(path) {
|
||||
this.currentPath = path
|
||||
const arr = path.split('.')
|
||||
this.currentType = arr[arr.length - 1]
|
||||
this.previewVisible = true
|
||||
}
|
||||
}
|
||||
}
|
||||
</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;
|
||||
}
|
||||
::v-deep .el-table--border th.gutter:last-of-type{
|
||||
border: none;
|
||||
}
|
||||
::v-deep .el-table, .el-table__expanded-cell {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
|
||||
::v-deep .el-table th, .el-table tr {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
::v-deep .el-table__body tr > td{
|
||||
background-color:#000 !important;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
::v-deep .el-table__body tr:hover > td{
|
||||
background-color:#858282 !important;
|
||||
color: #fff;
|
||||
border-color:#444444;
|
||||
}
|
||||
::v-deep .el-table--border th.gutter:last-of-type{
|
||||
border: none;
|
||||
}
|
||||
::v-deep .el-card__header{
|
||||
border: none;
|
||||
padding: 10px;
|
||||
}
|
||||
::v-deep .el-upload-list--picture-card .el-upload-list__item{
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
}
|
||||
::v-deep .el-upload--picture-card{
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
line-height: 40px;
|
||||
}
|
||||
::v-deep .el-dialog{
|
||||
background: #1e1e1e;
|
||||
border: 1px solid #ddd;
|
||||
color: #ddd;
|
||||
.el-dialog__title{
|
||||
color:#fff;
|
||||
}
|
||||
.el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
.el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
.el-form-item__label{
|
||||
color: #dfdfdf
|
||||
}
|
||||
}
|
||||
}
|
||||
::v-deep .el-switch__label{
|
||||
color:#fff;
|
||||
}
|
||||
::v-deep .el-switch__label.is-active{
|
||||
color: #428bca;
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
</style>
|
||||
@@ -208,6 +208,8 @@
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
:visitTaskId="visitTaskId"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
@setFormItemData="setFormItemData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -315,4 +317,8 @@ export default {
|
||||
::v-deep .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
// ::v-deep .el-radio__input.is-disabled.is-checked .el-radio__inner {
|
||||
// background-color: #428bca;
|
||||
// border-color: #428bca;
|
||||
// }
|
||||
</style>
|
||||
|
||||
+670
-496
File diff suppressed because it is too large
Load Diff
+8
-3
@@ -40,14 +40,19 @@
|
||||
v-for="qs in questions"
|
||||
v-show="qs.ShowQuestion!==2"
|
||||
:key="qs.Id"
|
||||
:label="`${qs.QuestionName}`"
|
||||
:prop="qs.Id"
|
||||
:title="(qs.QuestionMark === 0 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2) && questionForm.IntrahepaticLesion) ? $t('trials:mRecist:warnning:msg1') : ''"
|
||||
:rules="[
|
||||
{ required: (qs.IsRequired === 0 || (qs.IsRequired ===1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10) || (qs.QuestionMark === 21 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2)) || (qs.QuestionMark === 0 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2))) && qs.Type!=='group' && qs.Type!=='summary',
|
||||
{ required: (qs.IsRequired === 0 || (qs.IsRequired ===1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10) || (qs.QuestionMark === 21 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2))) && qs.Type!=='group' && qs.Type!=='summary',
|
||||
message:['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
|
||||
]"
|
||||
>
|
||||
<span slot="label" style="display:inline-block;" >
|
||||
<el-tooltip v-if="qs.QuestionMark === 0 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2) && questionForm.IntrahepaticLesion" effect="dark" :content="$t('trials:mRecist:warnning:msg1')" placement="bottom">
|
||||
<i class='el-icon-warning' />
|
||||
</el-tooltip>
|
||||
{{ qs.QuestionName }}
|
||||
</span>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<template v-if="qs.Type==='input' || qs.Type==='number'">
|
||||
|
||||
|
||||
@@ -1,237 +1,283 @@
|
||||
const config = {
|
||||
"standards": [
|
||||
'standards': [
|
||||
{
|
||||
"type": 1,
|
||||
"name": "RECIST 1.1",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 1,
|
||||
'name': 'RECIST 1.1',
|
||||
'tools': [
|
||||
{
|
||||
'name': '直径测量工具',
|
||||
'icon': 'length',
|
||||
'toolName': 'Length',
|
||||
'i18nKey': 'trials:reading:button:length',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '长短径测量工具',
|
||||
'icon': 'bidirection',
|
||||
'toolName': 'Bidirectional',
|
||||
'i18nKey': 'trials:reading:button:bidirectional',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 2,
|
||||
"name": "Lugano 2014",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 2,
|
||||
'name': 'Lugano 2014',
|
||||
'tools': [
|
||||
{
|
||||
'name': '直径测量工具',
|
||||
'icon': 'length',
|
||||
'toolName': 'Length',
|
||||
'i18nKey': 'trials:reading:button:length',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '长短径测量工具',
|
||||
'icon': 'bidirection',
|
||||
'toolName': 'Bidirectional',
|
||||
'i18nKey': 'trials:reading:button:bidirectional',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 3,
|
||||
"name": "iRECIST",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 3,
|
||||
'name': 'iRECIST',
|
||||
'tools': [
|
||||
{
|
||||
'name': '直径测量工具',
|
||||
'icon': 'length',
|
||||
'toolName': 'Length',
|
||||
'i18nKey': 'trials:reading:button:length',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '长短径测量工具',
|
||||
'icon': 'bidirection',
|
||||
'toolName': 'Bidirectional',
|
||||
'i18nKey': 'trials:reading:button:bidirectional',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 7,
|
||||
"name": "mRECIST HCC",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 7,
|
||||
'name': 'mRECIST HCC',
|
||||
'tools': [
|
||||
{
|
||||
'name': '直径测量工具',
|
||||
'icon': 'length',
|
||||
'toolName': 'Length',
|
||||
'i18nKey': 'trials:reading:button:length',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '长短径测量工具',
|
||||
'icon': 'bidirection',
|
||||
'toolName': 'Bidirectional',
|
||||
'i18nKey': 'trials:reading:button:bidirectional',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 10,
|
||||
"name": "PCWG3",
|
||||
"tools": [
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 10,
|
||||
'name': 'PCWG3',
|
||||
'tools': [
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 17,
|
||||
"name": "PCWG3",
|
||||
"tools": [
|
||||
{
|
||||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 17,
|
||||
'name': 'PCWG3',
|
||||
'tools': [
|
||||
{
|
||||
'name': '直径测量工具',
|
||||
'icon': 'length',
|
||||
'toolName': 'Length',
|
||||
'i18nKey': 'trials:reading:button:length',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": 19,
|
||||
"name": "IVUS定量评估",
|
||||
"tools": []
|
||||
'type': 19,
|
||||
'name': 'IVUS定量评估',
|
||||
'tools': []
|
||||
},
|
||||
{
|
||||
"type": 20,
|
||||
"name": "OCT定量评估",
|
||||
"tools": []
|
||||
'type': 20,
|
||||
'name': 'OCT定量评估',
|
||||
'tools': []
|
||||
},
|
||||
{
|
||||
"type": 21,
|
||||
"name": "MRI-PDFF",
|
||||
"tools": [
|
||||
{
|
||||
"name": "圆形测量",
|
||||
"icon": "oval",
|
||||
"toolName": "Probe",
|
||||
"i18nKey": "trials:reading:button:circle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
'type': 21,
|
||||
'name': 'MRI-PDFF',
|
||||
'tools': [
|
||||
{
|
||||
'name': '圆形测量',
|
||||
'icon': 'oval',
|
||||
'toolName': 'Probe',
|
||||
'i18nKey': 'trials:reading:button:circle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
'customizeStandards': [
|
||||
{
|
||||
'name': '直径测量工具',
|
||||
'icon': 'length',
|
||||
'toolName': 'Length',
|
||||
'i18nKey': 'trials:reading:button:length',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
'name': '长短径测量工具',
|
||||
'icon': 'bidirection',
|
||||
'toolName': 'Bidirectional',
|
||||
'i18nKey': 'trials:reading:button:bidirectional',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
'name': '矩形工具',
|
||||
'icon': 'rectangle',
|
||||
'toolName': 'RectangleROI',
|
||||
'i18nKey': 'trials:reading:button:rectangle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
'name': '箭头工具',
|
||||
'icon': 'arrow',
|
||||
'toolName': 'ArrowAnnotate',
|
||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
},
|
||||
{
|
||||
'name': '椭圆工具',
|
||||
'icon': 'oval',
|
||||
'toolName': 'CircleROI',
|
||||
'i18nKey': 'trials:reading:button:Circle',
|
||||
'isDisabled': false,
|
||||
'disabledReason': ''
|
||||
}
|
||||
]
|
||||
}
|
||||
const getTools = (criterionType) => {
|
||||
const standard = config.standards.find(s => s.type === criterionType);
|
||||
return standard?.tools || [];
|
||||
};
|
||||
export {config, getTools}
|
||||
const standard = config.standards.find(s => s.type === criterionType)
|
||||
return standard?.tools || []
|
||||
}
|
||||
const getCustomizeStandardsTools = (toolNames) => {
|
||||
const filteredTools = config.customizeStandards.filter(item => toolNames.includes(item.toolName))
|
||||
return filteredTools || []
|
||||
}
|
||||
export { config, getTools, getCustomizeStandardsTools }
|
||||
|
||||
@@ -0,0 +1,305 @@
|
||||
|
||||
import {
|
||||
VolumeViewport,
|
||||
utilities as csUtils,
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
const {
|
||||
utilities,
|
||||
annotation,
|
||||
drawing
|
||||
|
||||
} = cornerstoneTools
|
||||
|
||||
const { getAnnotations } = annotation.state
|
||||
const { isAnnotationVisible } = annotation.visibility
|
||||
const { isAnnotationLocked } = annotation.locking
|
||||
|
||||
|
||||
const drawHandlesSvg = drawing.drawHandles
|
||||
const drawRectSvg = drawing.drawRectByCoordinates
|
||||
const drawLinkedTextBoxSvg = drawing.drawLinkedTextBox
|
||||
const { getTextBoxCoordsCanvas } = utilities.drawing
|
||||
|
||||
|
||||
/**
|
||||
* RectangleROIAnnotation let you draw annotations that measures the statistics
|
||||
* such as area, max, mean and stdDev of a Rectangular region of interest.
|
||||
* You can use RectangleROIAnnotation in all perpendicular views (axial, sagittal, coronal).
|
||||
* Note: annotation tools in cornerstone3DTools exists in the exact location
|
||||
* in the physical 3d space, as a result, by default, all annotations that are
|
||||
* drawing in the same frameOfReference will get shared between viewports that
|
||||
* are in the same frameOfReference. RectangleROI tool's text box lines are dynamically
|
||||
* generated based on the viewport's underlying Modality. For instance, if
|
||||
* the viewport is displaying CT, the text box will shown the statistics in Hounsfield units,
|
||||
* and if the viewport is displaying PET, the text box will show the statistics in
|
||||
* SUV units.
|
||||
*
|
||||
* The resulting annotation's data (statistics) and metadata (the
|
||||
* state of the viewport while drawing was happening) will get added to the
|
||||
* ToolState manager and can be accessed from the ToolState by calling getAnnotations
|
||||
* or similar methods.
|
||||
*
|
||||
* ```js
|
||||
* cornerstoneTools.addTool(RectangleROITool)
|
||||
*
|
||||
* const toolGroup = ToolGroupManager.createToolGroup('toolGroupId')
|
||||
*
|
||||
* toolGroup.addTool(RectangleROITool.toolName)
|
||||
*
|
||||
* toolGroup.addViewport('viewportId', 'renderingEngineId')
|
||||
*
|
||||
* toolGroup.setToolActive(RectangleROITool.toolName, {
|
||||
* bindings: [
|
||||
* {
|
||||
* mouseButton: MouseBindings.Primary, // Left Click
|
||||
* },
|
||||
* ],
|
||||
* })
|
||||
* ```
|
||||
*
|
||||
* Read more in the Docs section of the website.
|
||||
*/
|
||||
|
||||
class RectangleROITool extends cornerstoneTools.RectangleROITool {
|
||||
constructor(
|
||||
toolProps,
|
||||
defaultToolProps
|
||||
) {
|
||||
super(toolProps, defaultToolProps);
|
||||
}
|
||||
|
||||
/**
|
||||
* it is used to draw the rectangleROI annotation in each
|
||||
* request animation frame. It calculates the updated cached statistics if
|
||||
* data is invalidated and cache it.
|
||||
*
|
||||
* @param enabledElement - The Cornerstone's enabledElement.
|
||||
* @param svgDrawingHelper - The svgDrawingHelper providing the context for drawing.
|
||||
*/
|
||||
renderAnnotation = (
|
||||
enabledElement,
|
||||
svgDrawingHelper
|
||||
) => {
|
||||
let renderStatus = false;
|
||||
const { viewport } = enabledElement;
|
||||
const { element } = viewport;
|
||||
|
||||
let annotations = getAnnotations(this.getToolName(), element);
|
||||
|
||||
if (!annotations?.length) {
|
||||
return renderStatus;
|
||||
}
|
||||
|
||||
annotations = this.filterInteractableAnnotationsForElement(
|
||||
element,
|
||||
annotations
|
||||
);
|
||||
|
||||
if (!annotations?.length) {
|
||||
return renderStatus;
|
||||
}
|
||||
|
||||
const targetId = this.getTargetId(viewport);
|
||||
const renderingEngine = viewport.getRenderingEngine();
|
||||
|
||||
const styleSpecifier = {
|
||||
toolGroupId: this.toolGroupId,
|
||||
toolName: this.getToolName(),
|
||||
viewportId: enabledElement.viewport.id,
|
||||
};
|
||||
|
||||
for (let i = 0; i < annotations.length; i++) {
|
||||
const annotation = annotations[i];
|
||||
const { annotationUID, data } = annotation;
|
||||
const { points, activeHandleIndex } = data.handles;
|
||||
const canvasCoordinates = points.map((p) => viewport.worldToCanvas(p));
|
||||
|
||||
styleSpecifier.annotationUID = annotationUID;
|
||||
|
||||
const { color, lineWidth, lineDash } = this.getAnnotationStyle({
|
||||
annotation,
|
||||
styleSpecifier,
|
||||
});
|
||||
|
||||
const { viewPlaneNormal, viewUp } = viewport.getCamera();
|
||||
|
||||
// If cachedStats does not exist, or the unit is missing (as part of import/hydration etc.),
|
||||
// force to recalculate the stats from the points
|
||||
if (
|
||||
!data.cachedStats[targetId] ||
|
||||
data.cachedStats[targetId].areaUnit == null
|
||||
) {
|
||||
data.cachedStats[targetId] = {
|
||||
Modality: null,
|
||||
area: null,
|
||||
max: null,
|
||||
mean: null,
|
||||
stdDev: null,
|
||||
areaUnit: null,
|
||||
};
|
||||
|
||||
this._calculateCachedStats(
|
||||
annotation,
|
||||
viewPlaneNormal,
|
||||
viewUp,
|
||||
renderingEngine,
|
||||
enabledElement
|
||||
);
|
||||
} else if (annotation.invalidated) {
|
||||
this._throttledCalculateCachedStats(
|
||||
annotation,
|
||||
viewPlaneNormal,
|
||||
viewUp,
|
||||
renderingEngine,
|
||||
enabledElement
|
||||
);
|
||||
|
||||
// If the invalidated data is as a result of volumeViewport manipulation
|
||||
// of the tools, we need to invalidate the related stackViewports data if
|
||||
// they are not at the referencedImageId, so that
|
||||
// when scrolling to the related slice in which the tool were manipulated
|
||||
// we re-render the correct tool position. This is due to stackViewport
|
||||
// which doesn't have the full volume at each time, and we are only working
|
||||
// on one slice at a time.
|
||||
if (viewport instanceof VolumeViewport) {
|
||||
const { referencedImageId } = annotation.metadata;
|
||||
|
||||
// invalidate all the relevant stackViewports if they are not
|
||||
// at the referencedImageId
|
||||
for (const targetId in data.cachedStats) {
|
||||
if (targetId.startsWith('imageId')) {
|
||||
const viewports = renderingEngine.getStackViewports();
|
||||
|
||||
const invalidatedStack = viewports.find((vp) => {
|
||||
// The stack viewport that contains the imageId but is not
|
||||
// showing it currently
|
||||
const referencedImageURI =
|
||||
csUtils.imageIdToURI(referencedImageId);
|
||||
const hasImageURI = vp.hasImageURI(referencedImageURI);
|
||||
const currentImageURI = csUtils.imageIdToURI(
|
||||
vp.getCurrentImageId()
|
||||
);
|
||||
return hasImageURI && currentImageURI !== referencedImageURI;
|
||||
});
|
||||
|
||||
if (invalidatedStack) {
|
||||
delete data.cachedStats[targetId];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If rendering engine has been destroyed while rendering
|
||||
if (!viewport.getRenderingEngine()) {
|
||||
console.warn('Rendering Engine has been destroyed');
|
||||
return renderStatus;
|
||||
}
|
||||
|
||||
let activeHandleCanvasCoords;
|
||||
|
||||
if (!isAnnotationVisible(annotationUID)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (
|
||||
!isAnnotationLocked(annotationUID) &&
|
||||
!this.editData &&
|
||||
activeHandleIndex !== null && activeHandleIndex !== undefined
|
||||
) {
|
||||
// Not locked or creating and hovering over handle, so render handle.
|
||||
activeHandleCanvasCoords = [canvasCoordinates[activeHandleIndex]];
|
||||
}
|
||||
|
||||
if (activeHandleCanvasCoords) {
|
||||
const handleGroupUID = '0';
|
||||
|
||||
drawHandlesSvg(
|
||||
svgDrawingHelper,
|
||||
annotationUID,
|
||||
handleGroupUID,
|
||||
activeHandleCanvasCoords,
|
||||
{
|
||||
color,
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
const dataId = `${annotationUID}-rect`;
|
||||
const rectangleUID = '0';
|
||||
drawRectSvg(
|
||||
svgDrawingHelper,
|
||||
annotationUID,
|
||||
rectangleUID,
|
||||
canvasCoordinates,
|
||||
{
|
||||
color,
|
||||
lineDash,
|
||||
lineWidth,
|
||||
},
|
||||
dataId
|
||||
);
|
||||
|
||||
renderStatus = true;
|
||||
|
||||
const options = this.getLinkedTextBoxStyle(styleSpecifier, annotation);
|
||||
if (!options.visibility) {
|
||||
data.handles.textBox = {
|
||||
hasMoved: false,
|
||||
worldPosition: [0, 0, 0],
|
||||
worldBoundingBox: {
|
||||
topLeft: [0, 0, 0],
|
||||
topRight: [0, 0, 0],
|
||||
bottomLeft: [0, 0, 0],
|
||||
bottomRight: [0, 0, 0],
|
||||
},
|
||||
};
|
||||
continue;
|
||||
}
|
||||
|
||||
const textLines = this.configuration.getTextLines(data, targetId);
|
||||
if (!textLines || textLines.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!data.handles.textBox.hasMoved) {
|
||||
const canvasTextBoxCoords = getTextBoxCoordsCanvas(canvasCoordinates);
|
||||
|
||||
data.handles.textBox.worldPosition =
|
||||
viewport.canvasToWorld(canvasTextBoxCoords);
|
||||
}
|
||||
|
||||
const textBoxPosition = viewport.worldToCanvas(
|
||||
data.handles.textBox.worldPosition
|
||||
);
|
||||
|
||||
const textBoxUID = '1';
|
||||
const boundingBox = drawLinkedTextBoxSvg(
|
||||
svgDrawingHelper,
|
||||
annotationUID,
|
||||
textBoxUID,
|
||||
textLines,
|
||||
textBoxPosition,
|
||||
canvasCoordinates,
|
||||
{},
|
||||
options
|
||||
);
|
||||
|
||||
const { x: left, y: top, width, height } = boundingBox;
|
||||
|
||||
data.handles.textBox.worldBoundingBox = {
|
||||
topLeft: viewport.canvasToWorld([left, top]),
|
||||
topRight: viewport.canvasToWorld([left + width, top]),
|
||||
bottomLeft: viewport.canvasToWorld([left, top + height]),
|
||||
bottomRight: viewport.canvasToWorld([left + width, top + height]),
|
||||
};
|
||||
}
|
||||
|
||||
return renderStatus;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
export default RectangleROITool;
|
||||
@@ -302,7 +302,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
@@ -317,8 +317,9 @@ export default {
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
@@ -347,22 +348,23 @@ export default {
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
try {
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
reject()
|
||||
reject(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
@@ -358,7 +358,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
@@ -373,9 +373,9 @@ export default {
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
|
||||
if (valid) {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
@@ -404,22 +404,24 @@ export default {
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
try {
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
reject()
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
getBeforeAnswer(qsId, row) {
|
||||
|
||||
@@ -362,7 +362,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
@@ -377,8 +377,9 @@ export default {
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
@@ -407,22 +408,23 @@ export default {
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
try {
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
reject()
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
@@ -0,0 +1,481 @@
|
||||
<template>
|
||||
<el-form v-if="globalForm.taskList.length > 0" ref="globalRuleForm" :model="globalForm" class="global-form">
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:data="globalForm.taskList"
|
||||
>
|
||||
<!-- 访视名称 -->
|
||||
<el-table-column
|
||||
prop="BlindName"
|
||||
:label="$t('trials:globalReview:table:visitName')"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
/>
|
||||
<!-- 评估结果 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:globalReview:table:evaluationRes')"
|
||||
align="center"
|
||||
prop=""
|
||||
>
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(qs,index) in globalInfo.evaluationQsList"
|
||||
:key="index"
|
||||
prop=""
|
||||
:label="qs"
|
||||
show-overflow-tooltip
|
||||
width="150"
|
||||
>
|
||||
<!-- <template slot-scope="scope">
|
||||
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
||||
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template> -->
|
||||
<template slot-scope="scope">
|
||||
<template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
|
||||
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
||||
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 是否同意访视结果 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:globalReview:table:isAgreeEvaluationRes')"
|
||||
show-overflow-tooltip
|
||||
width="170"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-form-item
|
||||
v-if="readingTaskState<2"
|
||||
:prop="`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`"
|
||||
label=""
|
||||
:rules="[
|
||||
{ required: true,message: $t('common:ruleMessage:select'), trigger: ['change','blur']},
|
||||
]"
|
||||
class="form-item"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]"
|
||||
@change="handleAgreeOrNotChange(scope.$index,scope.row.AgreeOrNot[0].GlobalAnswerType)"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ReadingYesOrNo"
|
||||
:key="'AgreeOrNot' + item.value"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 1" type="primary">
|
||||
{{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 0" type="danger"> {{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}</el-tag>
|
||||
<span v-else />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<!-- 调整后结果 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:globalReview:table:adjustedRes')"
|
||||
align="center"
|
||||
prop=""
|
||||
>
|
||||
<template>
|
||||
<el-table-column
|
||||
v-for="(qs,index) in globalInfo.adjustedQsList"
|
||||
v-if="qs.isShow"
|
||||
:key="index"
|
||||
prop=""
|
||||
:label="qs.questionName"
|
||||
show-overflow-tooltip
|
||||
:min-width="index === 3 ? '200' : '200'"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
|
||||
<!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
|
||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
|
||||
</span> -->
|
||||
<el-form-item
|
||||
style="margin-bottom: 0;"
|
||||
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:scope.row.AfterQuestionList[index].GlobalAnswerType}`"
|
||||
label=""
|
||||
:rules="[
|
||||
{ required:parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0,message: $t('common:ruleMessage:specify'), trigger: ['change','blur']},
|
||||
]"
|
||||
>
|
||||
<label v-if="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0" />
|
||||
<!-- 裁判问题 -->
|
||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 0 ">
|
||||
<el-tooltip v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" placement="top-start">
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||
<el-option
|
||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value!==-1"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||
<el-option
|
||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||
<template v-if="getLesionCount(scope.row.LesionCountList,0)">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value!==-1 && item.value !== 1 && item.value !== 3"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="getLesionCount(scope.row.LesionCountList,1)">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value!==-1 && item.value !== 1 && item.value !== 6"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value === 1 || item.value === 2 || item.value === 4"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</template>
|
||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||
v-show="item.value !== 6"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
<!-- 评估更新类型 GlobalAnswerType:3 -->
|
||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||
<el-tooltip v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" placement="top-start">
|
||||
<el-select
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<el-option
|
||||
v-for="val in globalInfo.assessTypeList"
|
||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
|
||||
:key="val.Code"
|
||||
:label="language === 'en'?val.Value:val.ValueCN"
|
||||
:value="val.Code"
|
||||
/>
|
||||
</el-select>
|
||||
</el-tooltip>
|
||||
<el-select
|
||||
v-else
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||
style="width:90%;"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
>
|
||||
<el-option
|
||||
v-for="val in globalInfo.assessTypeList"
|
||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
|
||||
:key="val.Code"
|
||||
:label="language === 'en'?val.Value:val.ValueCN"
|
||||
:value="val.Code"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<el-input
|
||||
v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 1"
|
||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||
type="textarea"
|
||||
maxlength="100"
|
||||
show-word-limit
|
||||
style="width:90%;"
|
||||
:autosize="{ minRows: 2 }"
|
||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div v-else>
|
||||
|
||||
<span v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
|
||||
</span>
|
||||
<span v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode,parseInt(scope.row.AfterQuestionList[index].Answer)) }}
|
||||
</span>
|
||||
<span v-else>{{ scope.row.AfterQuestionList[index].Answer }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
circle
|
||||
:title="$t('trials:globalReview:table:view')"
|
||||
icon="el-icon-view"
|
||||
@click="handleView(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</el-form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { batchSubmitGlobalReadingInfo } from '@/api/trials'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
props: {
|
||||
globalInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
globalForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
assessTypes: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
mounted() {
|
||||
this.assessTypes = this.globalInfo.assessTypeList.filter(i => i.IsBaseLineUse === this.isBaseline)
|
||||
},
|
||||
methods: {
|
||||
getText(val, row, type) {
|
||||
if (type === 3) {
|
||||
var o = this.globalInfo.assessTypeList.find(v => {
|
||||
return parseInt(v.Code) === parseInt(val)
|
||||
})
|
||||
if (!o) {
|
||||
return ''
|
||||
}
|
||||
return this.language === 'en' ? o.Value : o.ValueCN
|
||||
} else if (row.TypeValue) {
|
||||
return val
|
||||
} else if (row.DictionaryCode) {
|
||||
return this.$fd(row.DictionaryCode, parseInt(val))
|
||||
}
|
||||
},
|
||||
|
||||
handleView(row) {
|
||||
var token = getToken()
|
||||
var visitTaskId = row.VisitTaskId
|
||||
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
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
}
|
||||
const routeData = this.$router.resolve({ path })
|
||||
var newWindow = window.open(routeData.href, '_blank')
|
||||
this.$emit('setOpenWindow', newWindow)
|
||||
},
|
||||
getLesionCount(lesionList, lesionType) {
|
||||
const lesion = lesionList.find(i => i.LesionType === lesionType)
|
||||
return lesion ? lesion.Count : 0
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
var answerList = []
|
||||
item.AfterQuestionList.map(i => {
|
||||
var obj = {}
|
||||
if (i.QuestionId) {
|
||||
obj.questionId = i.QuestionId
|
||||
obj.globalAnswerType = i.GlobalAnswerType
|
||||
obj.answer = this.globalForm[ `${index}${i.QuestionId}`]
|
||||
} else {
|
||||
obj.questionId = ''
|
||||
obj.globalAnswerType = i.GlobalAnswerType
|
||||
obj.answer = this.globalForm[ `${index}${i.GlobalAnswerType}`]
|
||||
}
|
||||
answerList.push(obj)
|
||||
})
|
||||
answerList.push({ questionId: '', globalAnswerType: item.AgreeOrNot[0].GlobalAnswerType,
|
||||
answer: this.globalForm[ `${index}${item.AgreeOrNot[0].GlobalAnswerType}`] })
|
||||
|
||||
visitTaskAnswerList.push({ visitTaskId: item.VisitTaskId, answerList: answerList })
|
||||
})
|
||||
var params = {
|
||||
globalTaskId: this.globalInfo.visitTaskId,
|
||||
subjectId: this.globalInfo.subjectId,
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
getBeforeAnswer(qsId, row) {
|
||||
var i = row.BeforeQuestionList.findIndex(item => item.QuestionName === qsId)
|
||||
|
||||
if (i > -1 && row.BeforeQuestionList[i].Answer) {
|
||||
var answer = ''
|
||||
if (row.BeforeQuestionList[i].DictionaryCode) {
|
||||
answer = row.BeforeQuestionList[i].Answer
|
||||
} else {
|
||||
answer = row.BeforeQuestionList[i].Answer
|
||||
}
|
||||
return answer
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
handleAgreeOrNotChange(index, globalAnswerType) {
|
||||
var agreeOrNot = parseInt(this.globalForm[`${index}${globalAnswerType}`])
|
||||
if (agreeOrNot === 1) {
|
||||
var qsList = this.globalForm.taskList[index].AfterQuestionList
|
||||
qsList.map(v => {
|
||||
if (v.QuestionId) {
|
||||
this.globalForm[`${index}${v.QuestionId}`] = ''
|
||||
} else if (v.GlobalAnswerType !== globalAnswerType) {
|
||||
this.globalForm[`${index}${v.GlobalAnswerType}`] = ''
|
||||
}
|
||||
})
|
||||
}
|
||||
console.log(this.globalForm)
|
||||
},
|
||||
getAssessType(v) {
|
||||
console.log(this.language)
|
||||
var i = this.globalInfo.assessTypeList.findIndex(i => String(i.Code) === String(v))
|
||||
if (i > -1) {
|
||||
return this.language === 'en' ? this.globalInfo.assessTypeList[i].Value : this.globalInfo.assessTypeList[i].ValueCN
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .el-form-item label:before {
|
||||
content: '*';
|
||||
color: #F56C6C;
|
||||
margin-right: 4px;
|
||||
}
|
||||
::v-deep .el-textarea .el-input__count{
|
||||
background: rgba(0,0,0,0);
|
||||
line-height: normal;
|
||||
}
|
||||
::v-deep .el-form-item{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.global-form{
|
||||
::v-deep .el-form-item__content{
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
::v-deep .form-item .el-form-item__error{
|
||||
top: 60%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -220,8 +220,9 @@ export default {
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
@@ -247,21 +248,24 @@ export default {
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
try {
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
reject()
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,7 +355,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
@@ -369,9 +369,10 @@ export default {
|
||||
return lesion ? lesion.Count : 0
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async(resolve, reject) => {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
@@ -400,22 +401,24 @@ export default {
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
try {
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
reject()
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
getBeforeAnswer(qsId, row) {
|
||||
|
||||
@@ -349,7 +349,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
@@ -364,8 +364,9 @@ export default {
|
||||
},
|
||||
handleSave(isPrompt = true) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
try {
|
||||
let valid = await this.$refs['globalRuleForm'].validate()
|
||||
if (valid) {
|
||||
this.loading = true
|
||||
var visitTaskAnswerList = []
|
||||
this.globalForm.taskList.forEach((item, index) => {
|
||||
@@ -394,22 +395,23 @@ export default {
|
||||
trialId: this.globalInfo.trialId,
|
||||
visitTaskAnswerList
|
||||
}
|
||||
try {
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
console.log(isPrompt)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
await batchSubmitGlobalReadingInfo(params)
|
||||
this.loading = false
|
||||
if (isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.$emit('getGlInfo')
|
||||
resolve(true)
|
||||
|
||||
} else {
|
||||
reject()
|
||||
resolve(false)
|
||||
}
|
||||
} catch(e) {
|
||||
console.log(e)
|
||||
this.loading = false
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
|
||||
})
|
||||
},
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
{{ $t('trials:globalReview:button:submit') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<CustomizeTable
|
||||
<customize-table
|
||||
v-if="CriterionType === 0 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
@@ -50,7 +50,7 @@
|
||||
@getGlInfo="getGlInfo"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
<RecistTable
|
||||
<recist-table
|
||||
v-if="CriterionType === 1 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
@@ -59,7 +59,7 @@
|
||||
@getGlInfo="getGlInfo"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
<LuganoTable
|
||||
<lugano-table
|
||||
v-if="CriterionType === 2 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
@@ -69,7 +69,7 @@
|
||||
@handleView="handleView"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
<PCWG3Table
|
||||
<pcwg3-table
|
||||
v-if="CriterionType === 10 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
@@ -79,7 +79,7 @@
|
||||
@handleView="handleView"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
<IRecistTable
|
||||
<irecist-table
|
||||
v-if="CriterionType === 3 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
@@ -88,7 +88,7 @@
|
||||
@getGlInfo="getGlInfo"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
<RecistBMTable
|
||||
<recistbm-table
|
||||
v-if="CriterionType === 17 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
@@ -97,7 +97,16 @@
|
||||
@getGlInfo="getGlInfo"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
|
||||
<mrecist-table
|
||||
v-if="CriterionType === 7 && Object.keys(globalInfo).length !== 0"
|
||||
ref="globalTbl"
|
||||
:global-info="globalInfo"
|
||||
:global-form="globalInfo.globalForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@getGlInfo="getGlInfo"
|
||||
@setOpenWindow="setOpenWindow"
|
||||
/>
|
||||
|
||||
</el-card>
|
||||
|
||||
<el-card v-if="isReadingShowPreviousResults" :body-style="{ padding: '10px' }" shadow="never">
|
||||
@@ -164,16 +173,17 @@ import const_ from '@/const/sign-code'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
import CustomizeTable from './components/CustomizeTable'
|
||||
import RecistTable from './components/RecistTable'
|
||||
import PCWG3Table from './components/PCWG3Table'
|
||||
import IRecistTable from './components/IRecistTable'
|
||||
import RecistBMTable from './components/RecistBMTable'
|
||||
import LuganoTable from './components/LuganoTable'
|
||||
import pcwg3Table from './components/PCWG3Table'
|
||||
import irecistTable from './components/IRecistTable'
|
||||
import recistbmTable from './components/RecistBMTable'
|
||||
import luganoTable from './components/LuganoTable'
|
||||
import mrecistTable from './components/MRecistTable.vue'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import store from '@/store'
|
||||
export default {
|
||||
name: 'GlobalReview',
|
||||
components: { CustomizeTable, RecistTable, PCWG3Table, IRecistTable, RecistBMTable,LuganoTable, SignForm },
|
||||
components: { CustomizeTable, RecistTable, pcwg3Table, irecistTable, recistbmTable,luganoTable,mrecistTable, SignForm },
|
||||
props: {
|
||||
trialId: {
|
||||
type: String,
|
||||
@@ -384,10 +394,13 @@ export default {
|
||||
.catch(() => {})
|
||||
} else {
|
||||
// 自动保存
|
||||
await this.$refs['globalTbl'].handleSave(false)
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
let res = await this.$refs['globalTbl'].handleSave(false)
|
||||
if (res) {
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
// 关闭签名框
|
||||
@@ -458,7 +471,7 @@ export default {
|
||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -328,7 +328,7 @@ export default {
|
||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
||||
|
||||
var path = "";
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${
|
||||
this.rowData.SubjectCode
|
||||
}&subjectId=${
|
||||
@@ -355,7 +355,7 @@ export default {
|
||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
||||
|
||||
var path = "";
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${
|
||||
this.rowData.SubjectCode
|
||||
}&subjectId=${this.rowData.SubjectId}&visitTaskId=${
|
||||
|
||||
@@ -320,7 +320,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.rowData.IsReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ export default {
|
||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||
var path = ''
|
||||
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
|
||||
@@ -178,7 +178,7 @@ export default {
|
||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||
var path = ''
|
||||
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
|
||||
@@ -787,7 +787,7 @@ export default {
|
||||
var trialReadingCriterionId = row.TrialReadingCriterionId
|
||||
var path = ''
|
||||
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||
|
||||
@@ -550,7 +550,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = ''
|
||||
if (readingTool === 0) {
|
||||
if (readingTool === 0 || readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -1112,7 +1112,7 @@ export default {
|
||||
lookReadingResults(row) {
|
||||
var token = getToken()
|
||||
var path
|
||||
if (row.ReadingTool === 0) {
|
||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
||||
path = `/readingDicoms?trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -521,7 +521,7 @@ export default {
|
||||
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (row.ReadingTool === 0) {
|
||||
if (row.ReadingTool === 0 || row.ReadingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -32,7 +32,7 @@ export default {
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var path = ''
|
||||
if (this.readingTool === 0) {
|
||||
if (this.readingTool === 0 || this.readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
||||
|
||||
@@ -436,7 +436,7 @@ export default {
|
||||
)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (this.readingTool === 0) {
|
||||
if (this.readingTool === 0 || this.readingTool === 2) {
|
||||
if (this.criterionType === 0 && this.trialId === '08dd28b3-6843-fc05-0242-ac1301000000') {
|
||||
path = `/fusion?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&studyId=62b3dfc4-1e04-4180-910d-fe595f398361&ctseriesId=1bd24f53-d419-32e5-92d4-2b04640aaa65&ptseriesId=2b7b128d-8c3f-8357-ad14-e38f3acbbdff&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&TokenKey=${token}&lang=${this.$i18n.locale}`
|
||||
} else {
|
||||
@@ -468,7 +468,7 @@ export default {
|
||||
)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (this.readingTool === 0) {
|
||||
if (this.readingTool === 0 || this.readingTool === 2 ) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -614,7 +614,7 @@ export default {
|
||||
}
|
||||
var token = getToken()
|
||||
var path
|
||||
if (row.ReadingTool === 0) {
|
||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -601,10 +601,29 @@
|
||||
</el-dialog>
|
||||
<!-- 退回影响任务列表/已影响任务列表 -->
|
||||
<el-dialog v-if="ReReadingOrBackVisible" :title="opentype === 'read'
|
||||
? $t('trials:reviewTrack:dialog:backImpactList')
|
||||
? $t('trials:reviewTrack:action:back')
|
||||
: $t('trials:reviewTrack:dialog:impactList')
|
||||
" :visible.sync="ReReadingOrBackVisible" width="1460px" append-to-body :close-on-click-modal="false"
|
||||
custom-class="base-dialog-wrapper">
|
||||
<el-form ref="backReasonForm" :rules="rules" :model="backforReasonForm" class="demo-ruleForm" size="small"
|
||||
label-width="180px">
|
||||
<!-- 申请原因 -->
|
||||
<el-divider content-position="left">
|
||||
{{ $t('trials:reviewTrack:applyReread:title:backReason') }}
|
||||
</el-divider>
|
||||
<!-- 申请原因 -->
|
||||
<el-form-item :label="$t('trials:reviewTrack:applyReread:title:backReason')" prop="pmBackReason" :rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:specify') },
|
||||
]">
|
||||
<el-input v-model="backforReasonForm.pmBackReason" style="width: 400px" type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }" :placeholder="$t('common:ruleMessage:specify')" maxlength="500"
|
||||
show-word-limit />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<!-- 影响的任务列表 -->
|
||||
<el-divider content-position="left">{{
|
||||
$t('trials:reviewTrack:dialog:backImpactList')
|
||||
}}</el-divider>
|
||||
<div class="base-dialog-body">
|
||||
<el-table v-loading="loading" :data="InfluenceTaskList" stripe height="100" style="min-height: 400px">
|
||||
<!-- 任务编号 -->
|
||||
@@ -733,7 +752,8 @@
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer" v-if="opentype === 'read'">
|
||||
<!-- 取消 -->
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="ReReadingOrBackVisible = false">
|
||||
<el-button :disabled="btnLoading" size="small" type="primary"
|
||||
@click="ReReadingOrBackVisible = false, backforReasonForm = { pmBackReason: null }">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 确定 -->
|
||||
@@ -928,6 +948,9 @@ export default {
|
||||
Type: null,
|
||||
RequestReReadingReason: null,
|
||||
},
|
||||
backforReasonForm: {
|
||||
pmBackReason: null
|
||||
},
|
||||
rules: {
|
||||
Type: [
|
||||
{
|
||||
@@ -943,6 +966,13 @@ export default {
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
pmBackReason: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
RefereeAllocationVisible: false,
|
||||
trialId: this.$route.query.trialId,
|
||||
@@ -1075,10 +1105,16 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
PMSetTaskBack() {
|
||||
this.loading = true
|
||||
PMSetTaskBack(this.trialId, this.rowData.Id)
|
||||
.then((res) => {
|
||||
async PMSetTaskBack() {
|
||||
try {
|
||||
let validate = await this.$refs.backReasonForm.validate()
|
||||
console.log(validate, 'validate')
|
||||
if (!validate) return false
|
||||
// let data = Object.assign({}, this.backReasonForm)
|
||||
this.loading = true
|
||||
let res = await PMSetTaskBack(this.trialId, this.rowData.Id, this.backforReasonForm.pmBackReason)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.loading = false
|
||||
this.ReReadingOrBackVisible = false
|
||||
this.getList()
|
||||
@@ -1086,10 +1122,25 @@ export default {
|
||||
this.$message.success(
|
||||
this.$t('trials:reviewTrack:message:returnedSuccessfully')
|
||||
)
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
// this.loading = true
|
||||
// PMSetTaskBack(this.trialId, this.rowData.Id)
|
||||
// .then((res) => {
|
||||
// this.loading = false
|
||||
// this.ReReadingOrBackVisible = false
|
||||
// this.getList()
|
||||
// // '退回成功'
|
||||
// this.$message.success(
|
||||
// this.$t('trials:reviewTrack:message:returnedSuccessfully')
|
||||
// )
|
||||
// })
|
||||
// .catch(() => {
|
||||
// this.loading = false
|
||||
// })
|
||||
},
|
||||
openReReadingOrBackList(row) {
|
||||
this.loading = true
|
||||
@@ -1099,6 +1150,9 @@ export default {
|
||||
.then((res) => {
|
||||
this.InfluenceTaskList = res.Result
|
||||
this.ReReadingOtherInfo = res.OtherInfo
|
||||
this.backforReasonForm = {
|
||||
pmBackReason: null
|
||||
}
|
||||
this.ReReadingOrBackVisible = true
|
||||
this.loading = false
|
||||
})
|
||||
@@ -1113,7 +1167,7 @@ export default {
|
||||
}
|
||||
var token = getToken()
|
||||
var path
|
||||
if (row.ReadingTool === 0) {
|
||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
} else {
|
||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
<!-- 级别: -->
|
||||
<el-form-item :label="$t('trials:qcCfg:table:level')">
|
||||
<el-select v-model="searchData.IsDefeaultViewParent" style="width:120px;">
|
||||
<el-option v-for="item of $d.IsDefeaultViewParentLevel" :key="item.id" :value="item.value" :label="item.label" />
|
||||
<el-option v-for="item of $d.IsDefeaultViewParentLevel" :key="item.id" :value="item.value"
|
||||
:label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
@@ -25,87 +26,50 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto">
|
||||
<el-button type="primary" size="mini" :disabled="selectArr.length<=0" @click="handleSubmit">
|
||||
<el-button type="primary" size="mini" :disabled="selectArr.length <= 0" @click="handleSubmit">
|
||||
{{ $t('common:button:submit') }}
|
||||
</el-button>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<el-table
|
||||
ref="qsList"
|
||||
:data="list"
|
||||
stripe
|
||||
size="small"
|
||||
height="400"
|
||||
@selection-change="handleSelectChange"
|
||||
@select="handleselect"
|
||||
>
|
||||
<el-table ref="qsList" :data="list" stripe size="small" height="400" @selection-change="handleSelectChange"
|
||||
@select="handleselect" @select-all="handleselectAll">
|
||||
<el-table-column type="selection" align="left" width="45" :selectable="handleSelectTable" />
|
||||
<!-- 序号 -->
|
||||
<el-table-column
|
||||
prop="ShowOrder"
|
||||
:label="$t('trials:qcCfg:table:order')"
|
||||
width="60"
|
||||
/>
|
||||
<el-table-column prop="ShowOrder" :label="$t('trials:qcCfg:table:order')" width="60" />
|
||||
<!-- 审核问题 -->
|
||||
<el-table-column
|
||||
prop="QuestionName"
|
||||
:label="$t('trials:qcCfg:table:questionName')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="QuestionName" :label="$t('trials:qcCfg:table:questionName')" show-overflow-tooltip />
|
||||
<!-- 类型 -->
|
||||
<el-table-column
|
||||
prop="Type"
|
||||
:label="$t('trials:qcCfg:table:type')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="Type" :label="$t('trials:qcCfg:table:type')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QcType', scope.row.Type) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 选项 -->
|
||||
<el-table-column
|
||||
prop="TypeValue"
|
||||
:label="$t('trials:qcCfg:table:typeValue')"
|
||||
show-overflow-tooltip
|
||||
min-width="110"
|
||||
/>
|
||||
<el-table-column prop="TypeValue" :label="$t('trials:qcCfg:table:typeValue')" show-overflow-tooltip
|
||||
min-width="110" />
|
||||
|
||||
<!-- 父问题 -->
|
||||
<el-table-column
|
||||
prop="ParentShowOrder"
|
||||
:label="$t('trials:qcCfg:table:parentQs')"
|
||||
show-overflow-tooltip
|
||||
width="120"
|
||||
/>
|
||||
<el-table-column prop="ParentShowOrder" :label="$t('trials:qcCfg:table:parentQs')" show-overflow-tooltip
|
||||
width="120" />
|
||||
<!-- 父问题触发值 -->
|
||||
<el-table-column
|
||||
prop="ParentTriggerValue"
|
||||
:label="$t('trials:qcCfg:table:parentTriggerValue')"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column prop="ParentTriggerValue" :label="$t('trials:qcCfg:table:parentTriggerValue')"
|
||||
show-overflow-tooltip />
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:qcCfg:table:isRequired')"
|
||||
min-width="90"
|
||||
>
|
||||
<el-table-column prop="IsRequired" :label="$t('trials:qcCfg:table:isRequired')" min-width="90">
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsRequired) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 启用状态 -->
|
||||
<el-table-column
|
||||
prop="IsEnable"
|
||||
:label="$t('trials:qcCfg:table:isEnable')"
|
||||
min-width="120"
|
||||
>
|
||||
<el-table-column prop="IsEnable" :label="$t('trials:qcCfg:table:isEnable')" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<Pagination style="margin-top: 10px" class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
<Pagination style="margin-top: 10px" class="page" :total="total" :page.sync="searchData.PageIndex"
|
||||
:limit.sync="searchData.PageSize" @pagination="getList" />
|
||||
</box-content>
|
||||
</template>
|
||||
<script>
|
||||
@@ -144,7 +108,7 @@ export default {
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
created(){
|
||||
created() {
|
||||
this.trialId = this.$route.query.trialId;
|
||||
this.getList();
|
||||
},
|
||||
@@ -165,7 +129,13 @@ export default {
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
handleSelectChange(val) {
|
||||
this.selectArr = val
|
||||
// this.selectArr = val
|
||||
},
|
||||
handleselectAll(selection) {
|
||||
this.selectArr = []
|
||||
if (selection.length > 0) {
|
||||
this.selectArr = this.list
|
||||
}
|
||||
},
|
||||
handleselect(selection, row) {
|
||||
const selected = selection.length && selection.indexOf(row) !== -1
|
||||
@@ -175,6 +145,22 @@ export default {
|
||||
arr.map(item => {
|
||||
this.$refs.qsList.toggleRowSelection(item, selected)
|
||||
})
|
||||
let list = [...selection, ...arr]
|
||||
if (selected) {
|
||||
list.forEach(item => {
|
||||
if (!this.selectArr.find(d => d.Id === item.Id)) {
|
||||
this.selectArr.push(item)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
list = [row, ...arr]
|
||||
list.forEach(item => {
|
||||
let index = this.selectArr.indexOf(d => d.Id === item.Id)
|
||||
if (!~index) {
|
||||
this.selectArr.splice(index, 1)
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
handleSubmit() {
|
||||
this.loading = true
|
||||
|
||||
@@ -64,6 +64,28 @@
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 测量工具 -->
|
||||
<el-form-item
|
||||
v-if="CriterionType === 0 && (form.ReadingTool === 0 || form.ReadingTool === 2 ) && form.ReadingVersionEnum === 1"
|
||||
:label="$t('trials:readingUnit:readingRules:title:measureTool')"
|
||||
>
|
||||
<el-checkbox-group
|
||||
v-model="form.ReadingToolList"
|
||||
:disabled="
|
||||
isConfirm ||
|
||||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
||||
"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="tool in tools"
|
||||
:key="tool.toolName"
|
||||
:label="tool.toolName"
|
||||
name="ReadingToolList"
|
||||
>
|
||||
{{ $t(`${tool.i18nKey}`) }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<!--检查类型筛选-->
|
||||
<el-form-item
|
||||
:label="$t('trials:processCfg:form:IsImageFilter')"
|
||||
@@ -593,6 +615,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { getCriterionReadingInfo, setCriterionReadingInfo } from '@/api/trials'
|
||||
import { config } from '@/views/trials/trials-panel/reading/dicoms3D/components/toolConfig'
|
||||
export default {
|
||||
name: 'ReadingRules',
|
||||
props: {
|
||||
@@ -614,6 +637,8 @@ export default {
|
||||
TrialId: '',
|
||||
ImagePlatform: null,
|
||||
ReadingTool: 0,
|
||||
ReadingVersionEnum: null,
|
||||
ReadingToolList: [],
|
||||
ReadingTaskViewEnum: null,
|
||||
IsImageLabeled: null,
|
||||
IsReadingShowSubjectInfo: null,
|
||||
@@ -807,9 +832,14 @@ export default {
|
||||
modalityList: [],
|
||||
CriterionModalitys: [],
|
||||
modalityIsCheck: false, // 是否允许影像筛选
|
||||
tools: []
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
if (this.CriterionType === 0) {
|
||||
this.tools = [...config.customizeStandards]
|
||||
}
|
||||
|
||||
this.initPage()
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -116,7 +116,7 @@
|
||||
</el-form-item>
|
||||
<!-- 模板 -->
|
||||
<el-form-item
|
||||
v-if="form.ClinicalUploadType === 1"
|
||||
v-if="form.ClinicalUploadType === 1 && !isEN "
|
||||
:label="$t('trials:processCfg:title:module')"
|
||||
>
|
||||
<div class="upload-container">
|
||||
@@ -147,7 +147,7 @@
|
||||
</el-form-item>
|
||||
<!-- 英文模板 -->
|
||||
<el-form-item
|
||||
v-if="form.ClinicalUploadType === 1"
|
||||
v-if="form.ClinicalUploadType === 1 && isEN "
|
||||
:label="$t('trials:processCfg:title:enModule')"
|
||||
>
|
||||
<div class="upload-container">
|
||||
@@ -222,7 +222,11 @@ export default {
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
|
||||
computed:{
|
||||
isEN() {
|
||||
return this.$i18n.locale !== 'zh'
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
|
||||
@@ -1248,7 +1248,7 @@ export default {
|
||||
})
|
||||
// 查看关联操作
|
||||
|
||||
this.model_cfg2.title = `${this.$t('trials:auditRecord:title:viewRelationOperations')}--${this.$i18n.locale === 'en' ? this.currentRow.Description : this.currentRow.DescriptionCN}`
|
||||
this.model_cfg2.title = `${n ? this.$t('trials:auditRecord:title:viewRelationOperations2') : this.$t('trials:auditRecord:title:viewRelationOperations')}--${this.$i18n.locale === 'en' ? this.currentRow.Description : this.currentRow.DescriptionCN}`
|
||||
this.loading = true
|
||||
getInspectionList(searchData).then((res) => {
|
||||
this.list2 = res.CurrentPageData
|
||||
|
||||
-7
@@ -359,7 +359,6 @@ export default {
|
||||
status: 'add',
|
||||
upload: null,
|
||||
},
|
||||
DATA: {},
|
||||
doctorList: [],
|
||||
}
|
||||
},
|
||||
@@ -632,12 +631,6 @@ export default {
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
rowData: {
|
||||
handler() {
|
||||
this.DATA = Object.assign({}, this.rowData)
|
||||
},
|
||||
immediate: true,
|
||||
},
|
||||
},
|
||||
created() {
|
||||
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
|
||||
|
||||
+65
-82
@@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="chat-wrapper">
|
||||
<div v-if="recordContent.length>0" class="chat-content">
|
||||
<div v-for="(record,index) in recordContent" :key="`${record.CreateTime}${index}`">
|
||||
<div v-if="recordContent.length > 0" class="chat-content">
|
||||
<div v-for="(record, index) in recordContent" :key="`${record.CreateTime}${index}`">
|
||||
<div v-if="!record.IsCurrentUser" class="word">
|
||||
<img v-if="record.UserTypeEnum*1 === 8" :src="adminAvatar" alt="Admin">
|
||||
<img v-else-if="record.UserTypeEnum*1 === 1" :src="pmAvatar" alt="PM">
|
||||
<img v-else-if="record.UserTypeEnum*1 === 2" :src="crcAvatar" alt="CRC">
|
||||
<img v-if="record.UserTypeEnum * 1 === 8" :src="adminAvatar" alt="Admin">
|
||||
<img v-else-if="record.UserTypeEnum * 1 === 1" :src="pmAvatar" alt="PM">
|
||||
<img v-else-if="record.UserTypeEnum * 1 === 2" :src="crcAvatar" alt="CRC">
|
||||
<div class="info">
|
||||
<p class="user-info">
|
||||
<span style="font-weight:700;">{{ record.CreateUserName }} </span>
|
||||
@@ -24,9 +24,9 @@
|
||||
<div class="info-content" v-html="record.TalkContent" />
|
||||
</div>
|
||||
<!-- <img :src="record.headUrl"> -->
|
||||
<img v-if="record.UserTypeEnum*1 === 8" :src="adminAvatar" alt="Admin">
|
||||
<img v-else-if="record.UserTypeEnum*1 === 1" :src="pmAvatar" alt="PM">
|
||||
<img v-else-if="record.UserTypeEnum*1 === 2" :src="crcAvatar" alt="CRC">
|
||||
<img v-if="record.UserTypeEnum * 1 === 8" :src="adminAvatar" alt="Admin">
|
||||
<img v-else-if="record.UserTypeEnum * 1 === 1" :src="pmAvatar" alt="PM">
|
||||
<img v-else-if="record.UserTypeEnum * 1 === 2" :src="crcAvatar" alt="CRC">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -36,83 +36,50 @@
|
||||
</div>
|
||||
<div v-if="checkChallengeState !== 3 && checkState !== 11" class="chat-message">
|
||||
<div class="message">
|
||||
<el-input
|
||||
v-model="newMessage"
|
||||
v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
|
||||
type="textarea"
|
||||
:rows="2"
|
||||
/>
|
||||
<el-input v-model="newMessage" v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
|
||||
type="textarea" :rows="2" />
|
||||
</div>
|
||||
<div class="function">
|
||||
<!-- 申请回退 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:visit:consistency-check:apply-fallback']"
|
||||
type="primary"
|
||||
<el-button v-hasPermi="['trials:trials-panel:visit:consistency-check:apply-fallback']" type="primary"
|
||||
:disabled="!(checkState === 10 && (requestBackState === 0 || requestBackState === 3))"
|
||||
@click="handleApplyBack"
|
||||
>
|
||||
@click="handleApplyBack">
|
||||
{{ $t('trials:consistencyCheck:action:applyFallback') }}
|
||||
</el-button>
|
||||
<!-- 拒绝回退 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
|
||||
type="primary"
|
||||
:disabled="!(requestBackState === 1)"
|
||||
@click="handleRejectBack"
|
||||
>
|
||||
<el-button v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']" type="primary"
|
||||
:disabled="!(requestBackState === 1)" @click="handleRejectBack">
|
||||
{{ $t('trials:consistencyCheck:button:rejectBack') }}
|
||||
</el-button>
|
||||
<!-- 回退 -->
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
|
||||
type="primary"
|
||||
:disabled="!(requestBackState === 1)"
|
||||
@click="handleBack"
|
||||
>
|
||||
<el-button v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']" type="primary"
|
||||
:disabled="!(requestBackState === 1)" @click="handleBack">
|
||||
{{ $t('trials:consistencyCheck:action:fallback') }}
|
||||
</el-button>
|
||||
<!-- 发送 -->
|
||||
<el-button
|
||||
v-hasPermi="['role:pm']"
|
||||
:disabled="!(checkState === 10 && checkChallengeState !== 3) || newMessage === ''"
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="handleReply()"
|
||||
>
|
||||
<el-button v-hasPermi="['role:pm']"
|
||||
:disabled="!(checkState === 10 && checkChallengeState !== 3) || newMessage === ''" type="primary"
|
||||
:loading="btnLoading" @click="handleReply()">
|
||||
{{ $t('trials:consistencyCheck:button:sendMessage') }}
|
||||
</el-button>
|
||||
<!-- 回复 -->
|
||||
<el-button
|
||||
v-hasPermi="['role:crc']"
|
||||
<el-button v-hasPermi="['role:crc']" type="primary"
|
||||
:disabled="!(checkState === 10 && checkChallengeState !== 3) || (recordContent && recordContent.length > 0 ? recordContent[recordContent.length - 1].UserTypeEnum * 1 === 2 : false)"
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="handleCRCReply"
|
||||
>
|
||||
:loading="btnLoading" @click="handleCRCReply">
|
||||
{{ $t('trials:consistencyCheck:title:reply') }}
|
||||
</el-button>
|
||||
<!-- 关闭 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="close"
|
||||
>
|
||||
<el-button type="primary" :loading="btnLoading" @click="close">
|
||||
{{ $t('trials:consistencyCheck:title:close') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 回复一致性核查 -->
|
||||
<el-dialog
|
||||
v-if="sendMessageCRCVisible"
|
||||
v-dialogDrag
|
||||
:visible.sync="sendMessageCRCVisible"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
:width="'600px'"
|
||||
:title="$t('trials:consistencyCheck:title:replyConsistency')"
|
||||
>
|
||||
<crcSendMessage :crc-message-info="crcMessageInfo" @sendMessage="handleReply" />
|
||||
<el-dialog v-if="sendMessageCRCVisible" v-dialogDrag :visible.sync="sendMessageCRCVisible"
|
||||
:close-on-click-modal="false" append-to-body custom-class="base-dialog-wrapper" :width="'600px'"
|
||||
:title="$t('trials:consistencyCheck:title:replyConsistency')">
|
||||
<crcSendMessage :crc-message-info="crcMessageInfo" :visible.sync="sendMessageCRCVisible"
|
||||
@sendMessage="handleReply" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -277,46 +244,54 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.chat-wrapper{
|
||||
::-webkit-scrollbar {
|
||||
.chat-wrapper {
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.chat-content{
|
||||
width:100%;
|
||||
|
||||
.chat-content {
|
||||
width: 100%;
|
||||
padding: 20px;
|
||||
height: 500px;
|
||||
overflow-y: auto;
|
||||
.word{
|
||||
|
||||
.word {
|
||||
display: flex;
|
||||
margin-bottom: 20px;
|
||||
img{
|
||||
width:40px;
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.info{
|
||||
|
||||
.info {
|
||||
margin-left: 10px;
|
||||
.user-info{
|
||||
|
||||
.user-info {
|
||||
font-size: 12px;
|
||||
color:rgba(51,51,51,0.8);
|
||||
margin:0;
|
||||
color: rgba(51, 51, 51, 0.8);
|
||||
margin: 0;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: -5px;
|
||||
}
|
||||
.info-content{
|
||||
|
||||
.info-content {
|
||||
padding: 10px;
|
||||
font-size: 14px;
|
||||
background-color: #ebeef5;
|
||||
position: relative;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.info-content::before{
|
||||
|
||||
.info-content::before {
|
||||
position: absolute;
|
||||
left: -8px;
|
||||
top: 8px;
|
||||
@@ -327,29 +302,34 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.word-my{
|
||||
|
||||
.word-my {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 20px;
|
||||
img{
|
||||
|
||||
img {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
border-radius: 50%;
|
||||
}
|
||||
.info{
|
||||
|
||||
.info {
|
||||
width: 90%;
|
||||
margin-left: 10px;
|
||||
text-align: right;
|
||||
.user-info{
|
||||
|
||||
.user-info {
|
||||
font-size: 12px;
|
||||
color: rgba(51,51,51,0.8);
|
||||
color: rgba(51, 51, 51, 0.8);
|
||||
margin: 0;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
margin-top: -5px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
.info-content{
|
||||
|
||||
.info-content {
|
||||
position: relative;
|
||||
max-width: 70%;
|
||||
padding: 10px;
|
||||
@@ -361,7 +341,8 @@ export default {
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
.info-content::after{
|
||||
|
||||
.info-content::after {
|
||||
position: absolute;
|
||||
right: -8px;
|
||||
top: 8px;
|
||||
@@ -373,9 +354,11 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.chat-message{
|
||||
|
||||
.chat-message {
|
||||
padding: 0 50px;
|
||||
.function{
|
||||
|
||||
.function {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
+97
-112
@@ -6,98 +6,63 @@
|
||||
<div>
|
||||
<div style="padding: 10px;background: #f3f3f3;border-radius: 10px;margin-top: 10px">
|
||||
<div style="display:flex;margin-bottom: 10px;justify-content: space-between;align-items: center">
|
||||
<div>
|
||||
<div style="font-size: 18px;font-weight: blod;color: #409EFF">
|
||||
<!-- 请准确核实后录入当前访视的实际影像检查记录: -->
|
||||
{{ $t('trials:consistencyCheck:title:message20') }}
|
||||
</div>
|
||||
<!-- 添加 -->
|
||||
<el-button type="primary" size="mini" @click="addMsg">{{ $t('trials:consistencyCheck:title:add') }}</el-button>
|
||||
<el-button type="primary" size="mini" @click="addMsg">{{ $t('trials:consistencyCheck:title:add')
|
||||
}}</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
:data="msgList"
|
||||
>
|
||||
<el-table :data="msgList">
|
||||
<el-table-column type="index" width="40" />
|
||||
<!-- 检查日期 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:consistencyCheck:title:studyDate')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="" :label="$t('trials:consistencyCheck:title:studyDate')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.StudyDate }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 检查类型 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:consistencyCheck:title:studyModality')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="" :label="$t('trials:consistencyCheck:title:studyModality')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.Modality }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 已提交 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:consistencyCheck:title:submitted')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="" :label="$t('trials:consistencyCheck:title:submitted')" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsJoin) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 实际存在 -->
|
||||
<el-table-column
|
||||
prop=""
|
||||
:label="$t('trials:consistencyCheck:title:existed')"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<el-table-column prop="" :label="$t('trials:consistencyCheck:title:existed')" show-overflow-tooltip
|
||||
min-width="120px">
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.IsCheck"
|
||||
:disabled="!scope.row.IsJoin"
|
||||
@change="compareStudy"
|
||||
/>
|
||||
<el-switch v-model="scope.row.IsCheck" :active-text="$fd('YesOrNo', true)"
|
||||
:inactive-text="$fd('YesOrNo', false)" :disabled="!scope.row.IsJoin" @change="compareStudy" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
prop=""
|
||||
width="100px"
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
>
|
||||
<el-table-column prop="" width="100px" :label="$t('common:action:action')" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<!-- 删除 -->
|
||||
<el-button
|
||||
:disabled="scope.row.IsJoin"
|
||||
size="small"
|
||||
type="text"
|
||||
@click="moveMsg(scope.$index)"
|
||||
>
|
||||
{{ $t('trials:consistencyCheck:title:delete') }}
|
||||
<el-button :disabled="scope.row.IsJoin" size="small" icon="el-icon-delete"
|
||||
:title="$t('trials:consistencyCheck:title:delete')" circle @click="moveMsg(scope.$index)">
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<el-form
|
||||
ref="revenusForm"
|
||||
size="small"
|
||||
label-width="400px"
|
||||
:label-position="'top'"
|
||||
:rules="rules"
|
||||
:model="form"
|
||||
>
|
||||
<el-form ref="revenusForm" size="small" label-width="400px" :label-position="'top'" :rules="rules" :model="form"
|
||||
v-if="false">
|
||||
<!-- IRC与实际情况影像检查不一致的原因为: -->
|
||||
<el-form-item v-if="isLackOf" :label="$t('trials:consistencyCheck:title:title1')" prop="reason">
|
||||
<el-checkbox-group v-model="form.reason" style="display: flex;flex-direction: column">
|
||||
<el-checkbox style="display: block" :label="$t('trials:consistencyCheck:title:message9')">
|
||||
<!-- <el-checkbox style="display: block" :label="$t('trials:consistencyCheck:title:message9')">
|
||||
{{ $t('trials:consistencyCheck:title:message9') }}
|
||||
</el-checkbox>
|
||||
</el-checkbox> -->
|
||||
<el-checkbox style="display: block" :label="$t('trials:consistencyCheck:title:message10')">
|
||||
{{ $t('trials:consistencyCheck:title:message10') }}
|
||||
</el-checkbox>
|
||||
<el-checkbox style="display: block" :label="$t('trials:consistencyCheck:title:message11')">
|
||||
<el-checkbox disabled style="display: block" :label="$t('trials:consistencyCheck:title:message11')">
|
||||
{{ $t('trials:consistencyCheck:title:message11') }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
@@ -106,43 +71,29 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="function">
|
||||
<!-- 取消 -->
|
||||
<el-button @click="close">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 发送 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="handleReply"
|
||||
>
|
||||
<el-button type="primary" @click="handleReply">
|
||||
{{ $t('trials:consistencyCheck:button:sendMessage') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- 添加检查 -->
|
||||
<el-dialog
|
||||
v-if="studyVisible"
|
||||
v-dialogDrag
|
||||
:visible.sync="studyVisible"
|
||||
:close-on-click-modal="false"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
:width="'500px'"
|
||||
:title="$t('trials:consistencyCheck:title:addStudy')"
|
||||
>
|
||||
<el-dialog v-if="studyVisible" v-dialogDrag :visible.sync="studyVisible" :close-on-click-modal="false"
|
||||
append-to-body custom-class="base-dialog-wrapper" :width="'500px'"
|
||||
:title="$t('trials:consistencyCheck:title:addStudy')">
|
||||
<el-form>
|
||||
<div class="base-dialog-body">
|
||||
<!-- 检查日期 -->
|
||||
<el-form-item label-width="80px" :label="$t('trials:consistencyCheck:title:studyDate')">
|
||||
<el-date-picker
|
||||
v-model="typeInfo.StudyDate"
|
||||
style="width: 100%"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd"
|
||||
/>
|
||||
<el-date-picker v-model="typeInfo.StudyDate" style="width: 100%" type="date" value-format="yyyy-MM-dd" />
|
||||
</el-form-item>
|
||||
<!-- 检查类型 -->
|
||||
<el-form-item label-width="80px" :label="$t('trials:consistencyCheck:title:studyModality')">
|
||||
<el-select
|
||||
v-model="typeInfo.Modality"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option v-for="item of $d.Modality" :label="item.raw.Value" :value="item.value" :key="item.id"/>
|
||||
<el-select v-model="typeInfo.Modality" style="width: 100%">
|
||||
<el-option v-for="item of $d.Modality" :label="item.raw.Value" :value="item.value" :key="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</div>
|
||||
@@ -171,6 +122,10 @@ export default {
|
||||
TalkContent: null
|
||||
}
|
||||
}
|
||||
},
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -188,7 +143,7 @@ export default {
|
||||
EDCList: [],
|
||||
IRCList: [],
|
||||
form: {
|
||||
reason: []
|
||||
reason: [this.$t('trials:consistencyCheck:title:message11')]
|
||||
},
|
||||
rules: {
|
||||
reason: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }]
|
||||
@@ -196,12 +151,15 @@ export default {
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.crcMessageInfo.ParamInfoList.forEach(v => {
|
||||
this.msgList.push({ ...v, IsJoin: true, Ischeck: false })
|
||||
this.crcMessageInfo.ParamInfoList.forEach((v, i) => {
|
||||
this.msgList.push({ ...v, IsJoin: true, IsCheck: false, Id: this.getGuid(String(Date.now() + i)) })
|
||||
})
|
||||
this.compareStudy()
|
||||
},
|
||||
methods: {
|
||||
close() {
|
||||
this.$emit('update:visible', false)
|
||||
},
|
||||
compareStudy() {
|
||||
var isLackOf = false
|
||||
this.IRCList = []
|
||||
@@ -217,7 +175,9 @@ export default {
|
||||
this.studyVisible = false
|
||||
this.typeInfo = {
|
||||
StudyDate: null,
|
||||
Modality: null
|
||||
Modality: null,
|
||||
IsJoin: false,
|
||||
IsCheck: true
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
@@ -225,7 +185,7 @@ export default {
|
||||
this.$alert(this.$t('trials:consistencyCheck:title:title2'))// '请选择检查日期和检查类型'
|
||||
return
|
||||
}
|
||||
this.msgList.push({ ...this.typeInfo })
|
||||
this.msgList.push({ ...this.typeInfo, Id: this.getGuid(String(Date.now())) })
|
||||
this.compareStudy()
|
||||
this.studyVisible = false
|
||||
this.typeInfo = {
|
||||
@@ -248,14 +208,22 @@ export default {
|
||||
this.compareStudy()
|
||||
})
|
||||
},
|
||||
handleReply() {
|
||||
if (this.msgList.length === 0) {
|
||||
// '请录入真实的检查情况'
|
||||
this.$alert(this.$t('trials:consistencyCheck:title:title4'))
|
||||
return
|
||||
}
|
||||
this.$refs.revenusForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
async handleReply() {
|
||||
try {
|
||||
if (this.msgList.length === 0) {
|
||||
// '请录入真实的检查情况'
|
||||
this.$alert(this.$t('trials:consistencyCheck:title:title4'))
|
||||
return
|
||||
}
|
||||
// let valid = await this.$refs.revenusForm.validate()
|
||||
// if (!valid) return
|
||||
let confirm = true
|
||||
if (this.msgList.every(item => !item.IsCheck)) {
|
||||
confirm = await this.$confirm(this.$t('trials:consistencyCheck:title:confirm'), '', {
|
||||
showConfirmButton: false
|
||||
})
|
||||
}
|
||||
if (!confirm) return false
|
||||
var TalkContent = ''
|
||||
// '经核实,该受试者当前访视的实际影像检查如下:<br>'
|
||||
TalkContent += `${this.$t('trials:consistencyCheck:title:title5')}<br>`
|
||||
@@ -263,44 +231,61 @@ export default {
|
||||
// `${i + 1}.${v.StudyDate}的${v.Modality}影像检查<br>`
|
||||
let msg = this.$t('trials:consistencyCheck:title:title6').replace('yyyy', v.StudyDate)
|
||||
msg = msg.replace('xxx', v.Modality)
|
||||
TalkContent += `${i + 1}. ${msg}<br>`
|
||||
let message = `${i + 1}. ${msg}`
|
||||
let index = this.IRCList.findIndex(item => item.Id === v.Id)
|
||||
if (!!~index) {
|
||||
let data = this.IRCList[index]
|
||||
message += `(${data.IsJoin && !data.IsCheck ? this.$t('trials:consistencyCheck:title:title8') : this.$t('trials:consistencyCheck:title:title9')})<br>`
|
||||
} else {
|
||||
message += `(${this.$t('trials:consistencyCheck:title:title12')})<br>`
|
||||
}
|
||||
TalkContent += message
|
||||
})
|
||||
if (this.isLackOf) {
|
||||
TalkContent += '<br>'
|
||||
// 'IRC与实际情况不一致影像检查如下:<br>'
|
||||
TalkContent += `${this.$t('trials:consistencyCheck:title:title7')}<br>`
|
||||
this.IRCList.forEach((v, i) => {
|
||||
let msg = this.$t('trials:consistencyCheck:title:title6').replace('yyyy', v.StudyDate)
|
||||
msg = msg.replace('xxx', v.Modality)
|
||||
TalkContent += `${i + 1}.${msg}(${v.IsJoin && !v.IsCheck ? this.$t('trials:consistencyCheck:title:title8') : this.$t('trials:consistencyCheck:title:title9')})<br>`
|
||||
})
|
||||
if (this.form.reason.length > 0) {
|
||||
TalkContent += '<br>'
|
||||
// 'IRC与实际情况影像检查不一致的原因为:<br>'
|
||||
TalkContent += `${this.$t('trials:consistencyCheck:title:title10')}<br>`
|
||||
TalkContent += `<br>${this.$t('trials:consistencyCheck:title:title13')}`
|
||||
// TalkContent += '<br>'
|
||||
// // 'IRC与实际情况不一致影像检查如下:<br>'
|
||||
// TalkContent += `${this.$t('trials:consistencyCheck:title:title7')}<br>`
|
||||
// this.IRCList.forEach((v, i) => {
|
||||
// let msg = this.$t('trials:consistencyCheck:title:title6').replace('yyyy', v.StudyDate)
|
||||
// msg = msg.replace('xxx', v.Modality)
|
||||
// TalkContent += `${i + 1}.${msg}(${v.IsJoin && !v.IsCheck ? this.$t('trials:consistencyCheck:title:title8') : this.$t('trials:consistencyCheck:title:title9')})<br>`
|
||||
// })
|
||||
|
||||
this.form.reason.forEach((v, i) => {
|
||||
TalkContent += `${i + 1}.${v}<br>`
|
||||
})
|
||||
}
|
||||
|
||||
// if (this.form.reason.length > 0) {
|
||||
// TalkContent += '<br>'
|
||||
// // 'IRC与实际情况影像检查不一致的原因为:<br>'
|
||||
// TalkContent += `${this.$t('trials:consistencyCheck:title:title10')}<br>`
|
||||
|
||||
// this.form.reason.forEach((v, i) => {
|
||||
// TalkContent += `${i + 1}.${v}<br>`
|
||||
// })
|
||||
// }
|
||||
} else {
|
||||
// `<br>IRC与实际情况影像检查一致`
|
||||
TalkContent += `<br>${this.$t('trials:consistencyCheck:title:title11')}`
|
||||
// TalkContent += '<br>'
|
||||
// TalkContent += `${this.$t('trials:consistencyCheck:title:title10')}<br>`
|
||||
// TalkContent += `1.${this.$t('trials:consistencyCheck:title:message10')}<br>`
|
||||
}
|
||||
console.log(TalkContent)
|
||||
this.$emit('sendMessage', TalkContent, this.closeLoading)
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.function{
|
||||
.function {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
::v-deep .el-form--label-top .el-form-item__label{
|
||||
|
||||
::v-deep .el-form--label-top .el-form-item__label {
|
||||
padding-bottom: 0;
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
@@ -287,7 +287,7 @@
|
||||
<el-table-column
|
||||
v-if="hasPermi(['trials:trials-panel:visit:crc-question:send'])"
|
||||
:label="$t('common:action:action')"
|
||||
width="100"
|
||||
min-width="100"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
|
||||
@@ -1459,6 +1459,11 @@ export default {
|
||||
) {
|
||||
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
||||
}
|
||||
if (
|
||||
Math.abs(dicomInfo.uploadFileSize - dicomInfo.fileSize) < 5000
|
||||
) {
|
||||
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
||||
}
|
||||
}
|
||||
)
|
||||
if (!res || !res.url) {
|
||||
|
||||
@@ -102,8 +102,8 @@
|
||||
<!-- 预览 -->
|
||||
<el-button icon="el-icon-view" circle :title="$t('trials:uploadNonDicoms:action:preview')"
|
||||
:disabled="scope.row.FileCount === 0" @click.native.prevent="handlePreviewAllFiles(scope.row)" />
|
||||
<!-- 上传 -->
|
||||
<el-button v-if="allowAddOrEdit" icon="el-icon-upload2" circle :disabled="scope.row.IsDeleted"
|
||||
<!-- 上传 :disabled="scope.row.IsDeleted" -->
|
||||
<el-button v-if="allowAddOrEdit" icon="el-icon-upload2" circle
|
||||
:title="$t('trials:uploadNonDicoms:action:upload')" @click.native.prevent="handleUpload(scope.row)" />
|
||||
<!-- 上传视频 -->
|
||||
<!-- <el-button
|
||||
@@ -261,9 +261,9 @@
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<el-progress color="#409eff" :percentage="scope.row.size && scope.row.size > 0 ? ((scope.row.uploadFileSize * 100) / scope.row.size).toFixed(2) *
|
||||
1
|
||||
: ((scope.row.uploadFileSize * 100) / 1).toFixed(2) *
|
||||
1
|
||||
1
|
||||
: ((scope.row.uploadFileSize * 100) / 1).toFixed(2) *
|
||||
1
|
||||
" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -320,7 +320,7 @@
|
||||
scope.row.IsLostVisit
|
||||
" circle :title="$t('trials:crcUpload:action:submit')" @click="handleSubmit(scope.row)" />
|
||||
<!-- 退回 -->
|
||||
<el-button :disabled="scope.row.SubmitState * 1 < 2 || scope.row.IsImageBackApplying
|
||||
<el-button :disabled="scope.row.SubmitState * 1 < 2 || scope.row.IsImageBackApplying || scope.row.ChallengeState * 1 === 2
|
||||
" v-hasPermi="['trials:trials-panel:visit:crc-upload:back']" icon="el-icon-back" circle
|
||||
:title="$t('trials:crcUpload:action:back')" @click="imageBack(scope.row)" />
|
||||
<!-- 编辑 -->
|
||||
@@ -1007,15 +1007,30 @@ export default {
|
||||
// 申请影像退回
|
||||
async imageBack(row) {
|
||||
try {
|
||||
let confirm = await this.$confirm(this.$t("trials:crcUpload:confirmMessage:imageBack"))
|
||||
if (!confirm) return false
|
||||
let params = {
|
||||
SubjectVisitId: row.Id
|
||||
}
|
||||
let res = await requestImageBack(params)
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
this.$prompt(`<span style="color:#F56C6C">*</span><span>${this.$t("trials:crcUpload:confirmMessage:ApplyReason")}</span>`, this.$t("trials:crcUpload:confirmMessage:imageBack"), {
|
||||
confirmButtonText: this.$t("common:button:save"),
|
||||
cancelButtonText: this.$t("common:button:cancel"),
|
||||
dangerouslyUseHTMLString: true,
|
||||
inputValidator: (val) => {
|
||||
if (!val) return this.$t("common:ruleMessage:specify")
|
||||
},
|
||||
inputErrorMessage: this.$t("common:ruleMessage:specify")
|
||||
}).then(async ({ value }) => {
|
||||
let params = {
|
||||
SubjectVisitId: row.Id,
|
||||
ApplyReason: value
|
||||
}
|
||||
// return console.log(params)
|
||||
let res = await requestImageBack(params)
|
||||
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
// let confirm = await this.$confirm(this.$t("trials:crcUpload:confirmMessage:imageBack"))
|
||||
// if (!confirm) return false
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
@@ -1758,7 +1758,7 @@ export default {
|
||||
let obj = {
|
||||
name: `${data.SubjectCode}_${data.VisitName}_${this.$fd(
|
||||
'IsDicom',
|
||||
true
|
||||
false
|
||||
)}/${study.StudyCode}_${study.ImageDate.split(' ')[0]}_${
|
||||
study.Modality
|
||||
}/${item.FileName}`,
|
||||
|
||||
@@ -345,14 +345,14 @@
|
||||
<el-button v-hasPermi="['trials:trials-panel:visit:qc-check:receive']"
|
||||
:title="$t('trials:qcCheck:button:receive')" circle icon="el-icon-lock" :disabled="scope.row.PreliminaryAuditUserId === userId ||
|
||||
scope.row.IsTake ||
|
||||
scope.row.AuditState > 6
|
||||
scope.row.AuditState > 6 || scope.row.IsImageBackApplying
|
||||
" @click="handleReciveTask(scope.row, true)" />
|
||||
<!-- 释放:当前领取人才能释放 -->
|
||||
<!-- v-if="(scope.row.IsTake && (scope.row.AuditState*1 === 4 || scope.row.AuditState*1 === 6))" -->
|
||||
<el-button v-hasPermi="['trials:trials-panel:visit:qc-check:release']"
|
||||
:title="$t('trials:qcCheck:button:release')" circle icon="el-icon-unlock" :disabled="!(scope.row.CurrentActionUserId === userId) ||
|
||||
!scope.row.IsTake ||
|
||||
scope.row.AuditState * 1 > 6
|
||||
scope.row.AuditState * 1 > 6 || scope.row.IsImageBackApplying
|
||||
" @click="handleReciveTask(scope.row, false)" />
|
||||
<!-- 替换:1、针对同一访视质控,初审人不能替换复审人;2、当前领取人不能替换自己; -->
|
||||
<!-- v-if="(scope.row.IsTake && (scope.row.AuditState*1 === 4 || scope.row.AuditState*1 === 6))" -->
|
||||
@@ -360,7 +360,7 @@
|
||||
:title="$t('trials:crcQuestion:button:replaceTask')" circle icon="el-icon-refresh" :disabled="scope.row.CurrentActionUserId === userId ||
|
||||
scope.row.PreliminaryAuditUserId === userId ||
|
||||
!scope.row.IsTake ||
|
||||
scope.row.AuditState * 1 > 6
|
||||
scope.row.AuditState * 1 > 6 || scope.row.IsImageBackApplying
|
||||
" @click="handleReplaceTask(scope.row)" />
|
||||
<!-- 审核 -->
|
||||
<!-- v-if="scope.row.QCProcessEnum === 1 && scope.row.AuditState*1 === 4 && scope.row.IsTake" -->
|
||||
@@ -369,7 +369,7 @@
|
||||
? scope.row.CurrentActionUserId !== userId
|
||||
: false) ||
|
||||
!scope.row.IsTake ||
|
||||
scope.row.AuditState * 1 > 6
|
||||
scope.row.AuditState * 1 > 6 || scope.row.IsImageBackApplying
|
||||
" @click="handlePrimaryQC(scope.row)" />
|
||||
<!-- 初审 -->
|
||||
<!-- v-if="scope.row.QCProcessEnum === 2 && scope.row.AuditState*1 === 4 && scope.row.IsTake" -->
|
||||
@@ -380,7 +380,7 @@
|
||||
? scope.row.CurrentActionUserId !== userId
|
||||
: false) ||
|
||||
!scope.row.IsTake ||
|
||||
scope.row.AuditState * 1 > 6
|
||||
scope.row.AuditState * 1 > 6 || scope.row.IsImageBackApplying
|
||||
" @click="handlePrimaryQC(scope.row)" />
|
||||
<!-- 复审 -->
|
||||
<!-- v-if="scope.row.QCProcessEnum === 2 && scope.row.AuditState*1 === 6 && scope.row.IsTake && scope.row.PreliminaryAuditUserId!==userId" -->
|
||||
@@ -391,9 +391,10 @@
|
||||
!scope.row.IsTake ||
|
||||
scope.row.AuditState * 1 > 6 ||
|
||||
scope.row.CurrentActionUserId !== userId
|
||||
" @click="handleSecondaryQC(scope.row)" />
|
||||
|| scope.row.IsImageBackApplying" @click="handleSecondaryQC(scope.row)" />
|
||||
<!-- 退回 -->
|
||||
<el-button :disabled="scope.row.SubmitState * 1 < 2 || scope.row.IsImageBackApplying"
|
||||
<el-button
|
||||
:disabled="scope.row.SubmitState * 1 < 2 || scope.row.IsImageBackApplying || scope.row.ChallengeState * 1 === 2"
|
||||
v-hasPermi="['trials:trials-panel:visit:qc-check:back']" icon="el-icon-back" circle
|
||||
:title="$t('trials:qcCheck:button:back')" @click="imageBack(scope.row)" />
|
||||
</div>
|
||||
@@ -697,15 +698,30 @@ export default {
|
||||
// 申请影像退回
|
||||
async imageBack(row) {
|
||||
try {
|
||||
let confirm = await this.$confirm(this.$t("trials:qcCheck:confirmMessage:imageBack"))
|
||||
if (!confirm) return false
|
||||
let params = {
|
||||
SubjectVisitId: row.Id
|
||||
}
|
||||
let res = await requestImageBack(params)
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
this.$prompt(`<span style="color:#F56C6C">*</span><span>${this.$t("trials:crcUpload:confirmMessage:ApplyReason")}</span>`, this.$t("trials:crcUpload:confirmMessage:imageBack"), {
|
||||
confirmButtonText: this.$t("common:button:save"),
|
||||
cancelButtonText: this.$t("common:button:cancel"),
|
||||
dangerouslyUseHTMLString: true,
|
||||
inputValidator: (val) => {
|
||||
if (!val) return this.$t("common:ruleMessage:specify")
|
||||
},
|
||||
inputErrorMessage: this.$t("common:ruleMessage:specify")
|
||||
}).then(async ({ value }) => {
|
||||
let params = {
|
||||
SubjectVisitId: row.Id,
|
||||
ApplyReason: value
|
||||
}
|
||||
// return console.log(params)
|
||||
let res = await requestImageBack(params)
|
||||
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
// let confirm = await this.$confirm(this.$t("trials:crcUpload:confirmMessage:imageBack"))
|
||||
// if (!confirm) return false
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
@@ -108,17 +108,17 @@
|
||||
</el-table-column>
|
||||
<!-- 中心编号 -->
|
||||
<el-table-column prop="TrialSiteCode" :label="$t('trials:reuploadAudit:table:siteId')"
|
||||
show-overflow-tooltip sortable="custom" />
|
||||
show-overflow-tooltip sortable="custom" min-width="120px" />
|
||||
<!-- 受试者编号 -->
|
||||
<el-table-column prop="SubjectCode" :label="$t('trials:reuploadAudit:table:subjectId')"
|
||||
show-overflow-tooltip sortable="custom" width="120px" />
|
||||
show-overflow-tooltip sortable="custom" min-width="120px" />
|
||||
<!-- 访视名称 -->
|
||||
<el-table-column prop="VisitName" :label="$t('trials:reuploadAudit:table:visitName')"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
show-overflow-tooltip sortable="custom" min-width="120px">
|
||||
</el-table-column>
|
||||
<!-- 最晚拍片日期 -->
|
||||
<el-table-column prop="LatestScanDate" :label="$t('trials:reuploadAudit:table:lScanDate')"
|
||||
show-overflow-tooltip width="170" sortable="custom">
|
||||
show-overflow-tooltip min-width="170" sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-tooltip class="item" effect="dark" :content="`${scope.row.EarliestScanDate
|
||||
? moment(scope.row.EarliestScanDate).format('YYYY-MM-DD')
|
||||
@@ -139,40 +139,49 @@
|
||||
</el-table-column>
|
||||
<!-- 提交时间 -->
|
||||
<el-table-column prop="SubmitTime" :label="$t('trials:reuploadAudit:table:SubmitTime')"
|
||||
show-overflow-tooltip sortable="custom" width="150px" />
|
||||
show-overflow-tooltip sortable="custom" min-width="150px" />
|
||||
<!-- 申请人 -->
|
||||
<el-table-column prop="CreateUserFullName" :label="$t('trials:reuploadAudit:table:createUserFullName')"
|
||||
show-overflow-tooltip sortable="custom" />
|
||||
show-overflow-tooltip sortable="custom" min-width="120px" />
|
||||
<!-- 申请人角色 -->
|
||||
<el-table-column prop="ApplyUserRole" :label="$t('trials:reuploadAudit:table:applyUserRole')"
|
||||
show-overflow-tooltip sortable="custom" width="120px">
|
||||
show-overflow-tooltip sortable="custom" min-width="120px">
|
||||
<template slot-scope="scope">
|
||||
<span>{{ $fd('ImageBackApplyEnum',
|
||||
scope.row.ApplyUserRole) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 申请原因 -->
|
||||
<el-table-column prop="ApplyReason" :label="$t('trials:reuploadAudit:table:ApplyReason')"
|
||||
show-overflow-tooltip sortable="custom" min-width="120px" />
|
||||
<!-- 申请时间 -->
|
||||
<el-table-column prop="CreateTime" :label="$t('trials:reuploadAudit:table:createTime')"
|
||||
show-overflow-tooltip sortable="custom" width="150px" />
|
||||
show-overflow-tooltip sortable="custom" min-width="150px" />
|
||||
<!-- 审核状态 -->
|
||||
<el-table-column prop="ImageBackState" :label="$t('trials:reuploadAudit:table:imageBackState')"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
show-overflow-tooltip sortable="custom" min-width="120px">
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="['warning', '', 'danger'][scope.row.ImageBackState]">{{ $fd('ImageBackstateEnum',
|
||||
scope.row.ImageBackState) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 备注 -->
|
||||
<el-table-column prop="ResultRemark" :label="$t('trials:reuploadAudit:table:ResultRemark')"
|
||||
show-overflow-tooltip sortable="custom" min-width="120px" />
|
||||
<!-- 审核时间 -->
|
||||
<el-table-column prop="AuditTime" :label="$t('trials:reuploadAudit:table:auditTime')"
|
||||
show-overflow-tooltip sortable="custom" width="150px" />
|
||||
<el-table-column :label="$t('common:action:action')" fixed="right">
|
||||
show-overflow-tooltip sortable="custom" min-width="150px" />
|
||||
<el-table-column :label="$t('common:action:action')" fixed="right"
|
||||
v-if="hasPermi(['trials:trials-panel:visit:reupload-audit:agree'])" min-width="120px">
|
||||
<template slot-scope="scope">
|
||||
<el-button :title="$t('trials:reuploadAudit:button:auditYes')" circle
|
||||
:disabled="scope.row.ImageBackState > 0" icon="el-icon-check" size="mini"
|
||||
@click="audit(scope.row, 1)" />
|
||||
<el-button :title="$t('trials:reuploadAudit:button:auditNo')"
|
||||
<el-button :title="$t('trials:reuploadAudit:button:imageBack')"
|
||||
v-hasPermi="['trials:trials-panel:visit:reupload-audit:agree']" circle
|
||||
:disabled="scope.row.ImageBackState > 0" icon="el-icon-edit-outline" size="mini"
|
||||
@click="audit(scope.row)" />
|
||||
<!-- <el-button :title="$t('trials:reuploadAudit:button:auditNo')"
|
||||
v-hasPermi="['trials:trials-panel:visit:reupload-audit:refuse']"
|
||||
:disabled="scope.row.ImageBackState > 0" circle icon="el-icon-close" size="mini"
|
||||
@click="audit(scope.row, 2)" />
|
||||
@click="audit(scope.row, 2)" /> -->
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -181,6 +190,38 @@
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||
@pagination="getList" />
|
||||
</template>
|
||||
<base-model v-if="config.visible" :config="config">
|
||||
<template slot="dialog-body">
|
||||
<el-form ref="imageBackform" :model="form" class="demo-form-inline" :rules="rules"
|
||||
:label-width="isEN ? '150px' : '100px'">
|
||||
<el-form-item :label="$t('trials:reuploadAudit:table:Matters')" prop="Matters">
|
||||
<span>{{ rowData.title }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:reuploadAudit:form:ApplyReason')" prop="ApplyReason">
|
||||
<span>{{ rowData.ApplyReason }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:reuploadAudit:form:IsAgree')" prop="IsAgree">
|
||||
<el-radio-group v-model="form.IsAgree">
|
||||
<el-radio :label="true">{{ $t('trials:reuploadAudit:button:auditYes') }}</el-radio>
|
||||
<el-radio :label="false">{{ $t('trials:reuploadAudit:button:auditNo') }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:reuploadAudit:form:ResultRemark')" prop="ResultRemark">
|
||||
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder=""
|
||||
v-model="form.ResultRemark">
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button type="primary" @click="auditImageBack" :loading="loading">
|
||||
{{ $t('common:button:confirm') }}
|
||||
</el-button>
|
||||
<el-button @click="config.visible = false" :loading="loading">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
@@ -194,6 +235,7 @@ import {
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import moment from 'moment'
|
||||
import baseModel from '@/components/BaseModel'
|
||||
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
@@ -219,7 +261,8 @@ export default {
|
||||
name: 'QcCheck',
|
||||
components: {
|
||||
BaseContainer,
|
||||
Pagination
|
||||
Pagination,
|
||||
baseModel
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -233,9 +276,34 @@ export default {
|
||||
timeListC: [],
|
||||
timeList: [],
|
||||
trialId: null,
|
||||
moment
|
||||
moment,
|
||||
rowData: {},
|
||||
config: {
|
||||
visible: false,
|
||||
title: this.$t("trials:reuploadAudit:confirmMessage:imageBack"),
|
||||
width: '500px',
|
||||
appendToBody: true,
|
||||
},
|
||||
form: {
|
||||
IsAgree: null,
|
||||
ResultRemark: null
|
||||
},
|
||||
rules: {
|
||||
IsAgree: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
}
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isEN() {
|
||||
return this.$i18n.locale !== 'zh'
|
||||
},
|
||||
},
|
||||
watch: {
|
||||
list(val) {
|
||||
this.doLayout()
|
||||
@@ -249,26 +317,39 @@ export default {
|
||||
this.getVisitPlanOptions()
|
||||
},
|
||||
methods: {
|
||||
async audit(row, state) {
|
||||
async audit(row) {
|
||||
try {
|
||||
let message = this.$t("trials:reuploadAudit:confirmMessage:imageBack").replace("xxx", this.$fd("ImageBackstateEnum", state))
|
||||
let confirm = await this.$confirm(message)
|
||||
if (!confirm) return false
|
||||
let params = {
|
||||
IamgeBackRecordId: row.Id,
|
||||
IsAgree: state === 1 ? true : false
|
||||
}
|
||||
this.loading = true
|
||||
let res = await auditImageBack(params)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
}
|
||||
this.rowData = Object.assign({}, row)
|
||||
this.rowData.title = `${row.CreateUserFullName} (${this.$fd('ImageBackApplyEnum', row.ApplyUserRole)}) ${this.$t('trials:reuploadAudit:title:imageBack').replace('xxx', row.SubjectCode).replace('yyy', row.VisitName)}`
|
||||
Object.keys(this.form).forEach(key => {
|
||||
this.form[key] = null
|
||||
})
|
||||
this.config.visible = true
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
async auditImageBack() {
|
||||
try {
|
||||
let validate = await this.$refs.imageBackform.validate()
|
||||
if (!validate) return false
|
||||
let params = Object.assign({}, this.form)
|
||||
params.IamgeBackRecordId = this.rowData.Id
|
||||
// return console.log(params)
|
||||
this.loading = true
|
||||
let res = await auditImageBack(params)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.config.visible = false
|
||||
this.getList()
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
this.searchData.TrialId = this.trialId
|
||||
|
||||
@@ -15,15 +15,21 @@
|
||||
<div class="line"></div>
|
||||
<div class="contextmenu__item" @click="handleMenu('copy')">
|
||||
<i class="icon icon_copy" />
|
||||
<span>{{ $t('trials:trials-workbench:auditDocument:menu:copy') }}</span>
|
||||
<span>{{ $t('trials:trials-workbench:auditDocument:menu:copy') }}
|
||||
<span class="shortcut">{{ $t('trials:trials-workbench:auditDocument:shortcut:copy') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="contextmenu__item" @click="handleMenu('shear')">
|
||||
<i class="icon icon_shear" />
|
||||
<span>{{ $t('trials:trials-workbench:auditDocument:menu:shear') }}</span>
|
||||
<span>{{ $t('trials:trials-workbench:auditDocument:menu:shear') }}
|
||||
<span class="shortcut">{{ $t('trials:trials-workbench:auditDocument:shortcut:shear') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="contextmenu__item" @click="handleMenu('stickup')" v-if="checkList.length <= 1 && isCopy">
|
||||
<i class="icon icon_stickup" />
|
||||
<span>{{ $t('trials:trials-workbench:auditDocument:menu:stickup') }}</span>
|
||||
<span>{{ $t('trials:trials-workbench:auditDocument:menu:stickup') }}
|
||||
<span class="shortcut">{{ $t('trials:trials-workbench:auditDocument:shortcut:stickup') }}</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="contextmenu__item" @click="handleMenu('rename')" v-show="checkList.length <= 1">
|
||||
<i class="icon icon_rename" />
|
||||
@@ -197,6 +203,21 @@ export default {
|
||||
margin-right: 8px;
|
||||
}
|
||||
|
||||
.shortcut {
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
zoom: .95;
|
||||
font-weight: 200;
|
||||
color: #888;
|
||||
padding-left: 10px;
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
width: 65px;
|
||||
min-width: 50px;
|
||||
text-align: right;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/*打开*/
|
||||
.icon_open {
|
||||
color: #1890ff;
|
||||
|
||||
@@ -83,9 +83,13 @@
|
||||
@click="addRenameId(scope.row)"
|
||||
:title="$t('trials:trials-workbench:auditDocument:icon:rename')" />
|
||||
</span>
|
||||
<i :class="{ 'el-icon-circle-check': true, 'icon_check': true, isCheck: checkList.includes(scope.row.Id) }"
|
||||
<i :class="{ 'el-icon-success': true, 'icon_check': true, isCheck: checkList.includes(scope.row.Id) }"
|
||||
@click.stop="addCheck(scope.row)"
|
||||
v-if="(hoverId === scope.row.Id || checkList.includes(scope.row.Id)) && isManage" />
|
||||
<span class="version"
|
||||
v-if="(hoverId !== scope.row.Id && !checkList.includes(scope.row.Id)) && isManage && scope.row.HistoricalVersionsCount > 0">
|
||||
<i class="el-icon-warning-outline"></i>{{ scope.row.HistoricalVersionsCount }}
|
||||
</span>
|
||||
</div>
|
||||
<el-input v-model="scope.row.Name" :ref="`renameInp_${scope.row.Id}`" :autofocus="true"
|
||||
class="renameInp" @blur="rename(scope.row)" v-else />
|
||||
@@ -381,24 +385,25 @@ export default {
|
||||
async downLoad(list, row = {}) {
|
||||
if (!this.isManage) return false
|
||||
try {
|
||||
if (row.Id) {
|
||||
if (row.Id && row.AuditDocumentTypeEnum) {
|
||||
let name = row.Name.split('.')[1] ? row.Name : `${row.Name}.${row.FileFormat}`
|
||||
return await downLoadFile(
|
||||
this.OSSclientConfig.basePath + row.FilePath,
|
||||
row.Name
|
||||
name
|
||||
)
|
||||
}
|
||||
let arr = this.filterExternalIds(this.tableData, list)
|
||||
if (arr && arr.length === 1) {
|
||||
let data = this.getData(this.tableData, arr[0])
|
||||
if (data.AuditDocumentTypeEnum) {
|
||||
let name = data.Name.split('.')[1] ? data.Name : `${data.Name}.${data.FileFormat}`
|
||||
return await downLoadFile(
|
||||
this.OSSclientConfig.basePath + data.FilePath,
|
||||
data.Name
|
||||
name
|
||||
)
|
||||
} else {
|
||||
let dataArray = this.getDataPath([data])
|
||||
let files = this.formatDownloadFile(dataArray)
|
||||
console.log(files, 'files')
|
||||
let name = `${data.Name}_${new Date().getTime()}.zip`
|
||||
return await downLoadFile(files, name, 'zip')
|
||||
}
|
||||
@@ -484,7 +489,6 @@ export default {
|
||||
},
|
||||
getDataPath(list, str = '', ARRAY = []) {
|
||||
for (const item of list) {
|
||||
console.log(item.AuditDocumentTypeEnum, str)
|
||||
if (!str) {
|
||||
item.Path = item.Name
|
||||
} else {
|
||||
@@ -692,6 +696,8 @@ export default {
|
||||
async delData(Ids) {
|
||||
if (!this.isManage) return false
|
||||
try {
|
||||
let confirm = await this.$confirm(this.$t('trials:trials-workbench:auditDocument:delData'))
|
||||
if (!confirm) return false
|
||||
let data = { Ids }
|
||||
let res = await deleteAuditDocument(data)
|
||||
if (res.IsSuccess) {
|
||||
@@ -736,7 +742,6 @@ export default {
|
||||
// 新增列表数据
|
||||
async uplaodFile(list) {
|
||||
if (!this.isManage) return false
|
||||
console.log(list, 'list')
|
||||
let data = []
|
||||
if (this.config.isVersion) {
|
||||
data.push({
|
||||
@@ -809,7 +814,6 @@ export default {
|
||||
strKey.push(str)
|
||||
|
||||
})
|
||||
console.log(obj, 'obj')
|
||||
obj.children.push({
|
||||
ParentId: null,
|
||||
Name: item.FileName,
|
||||
@@ -964,6 +968,9 @@ export default {
|
||||
},
|
||||
// 单行左键双击(进入文件夹或者预览文件)
|
||||
handleRowDblclick(row, column, event) {
|
||||
if (this.$refs.contextmenu) {
|
||||
this.$refs.contextmenu.foo()
|
||||
}
|
||||
// 判断点击目标是否为展开按钮
|
||||
let isExpandButton = event.target.closest('.el-table__expand-icon');
|
||||
if (isExpandButton) return; // 阻止触发
|
||||
@@ -1022,7 +1029,7 @@ export default {
|
||||
handleMenu(data) {
|
||||
if (!this.isManage) return false
|
||||
let { key, row } = data
|
||||
console.log(key, row)
|
||||
// console.log(key, row)
|
||||
this.type = key;
|
||||
if (key === 'rename') {
|
||||
// this.renameId = this.checkList[0]
|
||||
@@ -1104,19 +1111,25 @@ export default {
|
||||
e.preventDefault();
|
||||
}
|
||||
if (e.ctrlKey && e.key === 'c') {
|
||||
e.preventDefault();
|
||||
this.type = 'copy'
|
||||
this.copy()
|
||||
// e.preventDefault();
|
||||
if (this.checkList.length > 0 && !this.renameId) {
|
||||
this.type = 'copy'
|
||||
this.copy()
|
||||
}
|
||||
|
||||
}
|
||||
if (e.ctrlKey && e.key === 'v') {
|
||||
e.preventDefault();
|
||||
// e.preventDefault();
|
||||
this.type = 'stickup'
|
||||
this.stickup()
|
||||
}
|
||||
if (e.ctrlKey && e.key === 'x') {
|
||||
e.preventDefault();
|
||||
this.type = 'shear'
|
||||
this.shear()
|
||||
// e.preventDefault();
|
||||
if (this.checkList.length > 0 && !this.renameId) {
|
||||
this.type = 'shear'
|
||||
this.shear()
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
// 键盘事件(松开)
|
||||
@@ -1131,8 +1144,8 @@ export default {
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.keydown);
|
||||
document.addEventListener('keyup', this.keyup);
|
||||
let table = document.getElementById("auditDocumentTable")
|
||||
table.addEventListener('click', this.docClick);
|
||||
// let table = document.getElementById("auditDocumentTable")
|
||||
document.addEventListener('click', this.docClick);
|
||||
this.getList()
|
||||
this.getBreadcrumbData()
|
||||
},
|
||||
@@ -1185,9 +1198,9 @@ export default {
|
||||
}
|
||||
|
||||
.last_catalogue {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
width: 36px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
text-align: center;
|
||||
border: 1px solid #ddd;
|
||||
// cursor: pointer;
|
||||
@@ -1207,8 +1220,8 @@ export default {
|
||||
border-left: none;
|
||||
padding: 0 10px;
|
||||
border-radius: 0 4px 4px 0;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
height: 36px;
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.catalogue_name {
|
||||
@@ -1226,6 +1239,7 @@ export default {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
|
||||
.name_box {
|
||||
display: flex;
|
||||
@@ -1241,6 +1255,22 @@ export default {
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
|
||||
.version {
|
||||
position: absolute;
|
||||
right: 0;
|
||||
top: 2px;
|
||||
background: #ff980021;
|
||||
color: #ff9800;
|
||||
font-size: 12px;
|
||||
padding: 0 3px;
|
||||
border-radius: 2px;
|
||||
z-index: 1;
|
||||
|
||||
i {
|
||||
margin-right: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon_edit {
|
||||
@@ -1254,13 +1284,15 @@ export default {
|
||||
}
|
||||
|
||||
.icon_check {
|
||||
font-size: 18px;
|
||||
font-size: 22px;
|
||||
cursor: pointer;
|
||||
color: rgba(0, 0, 0, 0.3);
|
||||
|
||||
&:hover {
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
z-index: 9;
|
||||
}
|
||||
|
||||
.isCheck {
|
||||
@@ -1271,6 +1303,20 @@ export default {
|
||||
background-color: #e5f3ff
|
||||
}
|
||||
|
||||
::v-deep .el-table {
|
||||
.caret-wrapper {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.sort-caret.ascending {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.sort-caret.descending {
|
||||
bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.icon_image {
|
||||
max-height: 20px;
|
||||
max-width: 20px;
|
||||
|
||||
@@ -13,91 +13,54 @@
|
||||
</el-col>
|
||||
<el-col :span="12" style="text-align: right">
|
||||
<h3>
|
||||
<Pagination
|
||||
class="page"
|
||||
:total="total"
|
||||
:page.sync="listQuery.pageIndex"
|
||||
:limit.sync="listQuery.pageSize"
|
||||
layout="total, sizes, prev, pager, next"
|
||||
:background="false"
|
||||
style="display: inline-block"
|
||||
@pagination="getList"
|
||||
/>
|
||||
<el-button
|
||||
icon="el-icon-refresh-left"
|
||||
size="small"
|
||||
circle
|
||||
:title="$t('common:button:reset')"
|
||||
@click="handleReset"
|
||||
/>
|
||||
<Pagination class="page" :total="total" :page.sync="listQuery.pageIndex" :limit.sync="listQuery.pageSize"
|
||||
layout="total, sizes, prev, pager, next" :background="false" style="display: inline-block"
|
||||
@pagination="getList" />
|
||||
<el-button icon="el-icon-refresh-left" size="small" circle :title="$t('common:button:reset')"
|
||||
@click="handleReset" />
|
||||
</h3>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- -->
|
||||
<el-table
|
||||
ref="needSignSysList"
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
:show-header="true"
|
||||
v-adaptive="{ bottomOffset: 45 }"
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
:default-sort="{ prop: 'UpdateTime', order: 'descending' }"
|
||||
>
|
||||
<el-table ref="needSignSysList" v-loading="listLoading" :data="list" :show-header="true"
|
||||
v-adaptive="{ bottomOffset: 45 }" height="100" @sort-change="handleSortByColumn"
|
||||
:default-sort="{ prop: 'UpdateTime', order: 'descending' }">
|
||||
<el-table-column type="index" width="40" />
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:fileType')"
|
||||
prop="FileType"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:fileName')"
|
||||
prop="Name"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:uploadTime')"
|
||||
prop="CreateTime"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:fileType')" prop="FileType" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:fileName')" prop="Name" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:AttachmentCount')" prop="AttachmentCount"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">{{ scope.row.AttachmentCount
|
||||
}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:uploadTime')" prop="CreateTime" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:SuggestFinishTime')" prop="SuggestFinishTime"
|
||||
show-overflow-tooltip sortable="custom" />
|
||||
<el-table-column :label="$t('common:action:action')" width="140">
|
||||
<template slot-scope="scope">
|
||||
<!-- 预览 -->
|
||||
<el-button
|
||||
icon="el-icon-view"
|
||||
circle
|
||||
v-if="isSigned"
|
||||
:title="$t('trials:self-attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
icon="el-icon-edit-outline"
|
||||
circle
|
||||
v-if="!isSigned"
|
||||
<el-button icon="el-icon-view" circle v-if="isSigned" :title="$t('trials:self-attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)" />
|
||||
<el-button icon="el-icon-edit-outline" circle v-if="!isSigned"
|
||||
:disabled="IsFirstSysDocNeedSign && !!~scope.row.DocTypeCode"
|
||||
:title="$t('trials:needSignSysDoc:action:sign')"
|
||||
@click="handleSign(scope.row)"
|
||||
/>
|
||||
:title="$t('trials:needSignSysDoc:action:sign')" @click="handleSign(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 预览/签署文件 -->
|
||||
<el-dialog
|
||||
v-if="previewVisible"
|
||||
:visible.sync="previewVisible"
|
||||
:title="title"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<span
|
||||
v-if="!currentIsConfirm"
|
||||
style="position: fixed; right: 75px; top: 14px"
|
||||
>
|
||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="title" :fullscreen="true" append-to-body
|
||||
custom-class="base-dialog-wrapper">
|
||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
||||
$t('trials:sysDocBeSigned:table:AttachmentCount') }} ({{
|
||||
currentRow.AttachmentCount }})</span>
|
||||
<span v-if="!currentIsConfirm" style="position: fixed; right: 75px; top: 14px">
|
||||
<span style="color: red; margin-right: 10px">
|
||||
<!-- 请仔细阅读文件,并签名确认 -->
|
||||
{{ $t('common:message:signTip') }}
|
||||
@@ -106,51 +69,33 @@
|
||||
}}</span>
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="timer !== null || duration === 0"
|
||||
:loading="btnLoading"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="timer !== null || duration === 0" :loading="btnLoading"
|
||||
@click="handleConfirm">
|
||||
{{ $t('common:button:sign') }}
|
||||
</el-button>
|
||||
</span>
|
||||
|
||||
<div
|
||||
class="base-modal-body"
|
||||
style="border: 2px solid #ccc; padding: 10px"
|
||||
>
|
||||
<PreviewFile
|
||||
v-if="previewVisible"
|
||||
:file-path="currentPath"
|
||||
:file-type="currentType"
|
||||
@getList="getList"
|
||||
/>
|
||||
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
||||
<PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" @getList="getList" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
|
||||
<!-- 签名弹框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
append-to-body
|
||||
>
|
||||
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
|
||||
append-to-body>
|
||||
<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
|
||||
:is-system-doc="currentRow.IsSystemDoc"
|
||||
:document-id="currentRow.Id"
|
||||
:file-name="fileName"
|
||||
@closeDialog="closeSignDialog"
|
||||
/>
|
||||
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName"
|
||||
@closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
||||
:isView="true" @getList="getList" />
|
||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible" :isView="true"
|
||||
v-if="perview_visible" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -162,6 +107,8 @@ import {
|
||||
import Pagination from '@/components/Pagination'
|
||||
import PreviewFile from '@/components/PreviewFile/index'
|
||||
import SignForm from '@/views/trials/trials-panel/attachments/self-attachment/components/SignForm'
|
||||
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
||||
import attachmentList from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentList'
|
||||
import { mapGetters } from 'vuex'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
@@ -173,7 +120,7 @@ const searchDataDefault = () => {
|
||||
}
|
||||
export default {
|
||||
name: 'NeedSignSysDoc',
|
||||
components: { Pagination, PreviewFile, SignForm },
|
||||
components: { Pagination, PreviewFile, SignForm, attachmentPreview, attachmentList },
|
||||
props: {
|
||||
isSigned: {
|
||||
type: Boolean,
|
||||
@@ -200,6 +147,13 @@ export default {
|
||||
currentIsConfirm: false,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
currentRow: {},
|
||||
SystemDocumentId: null,
|
||||
perview_visible: false,
|
||||
config: {
|
||||
visible: false,
|
||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
||||
width: '800px',
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -214,6 +168,16 @@ export default {
|
||||
...mapGetters(['IsFirstSysDocNeedSign']),
|
||||
},
|
||||
methods: {
|
||||
openAttachment(row, isList = false) {
|
||||
if (!row.AttachmentCount) return false
|
||||
this.SystemDocumentId = row.Id
|
||||
this.currentRow = { ...row }
|
||||
if (!isList) {
|
||||
this.perview_visible = true
|
||||
} else {
|
||||
this.config.visible = true
|
||||
}
|
||||
},
|
||||
// 预览
|
||||
handlePreview(row) {
|
||||
this.currentRow = { ...row }
|
||||
@@ -303,7 +267,7 @@ export default {
|
||||
.then(() => {
|
||||
this.previewVisible = false
|
||||
})
|
||||
.catch(() => {})
|
||||
.catch(() => { })
|
||||
} else {
|
||||
this.handleSign(res.Result)
|
||||
}
|
||||
|
||||
@@ -3,84 +3,57 @@
|
||||
<el-row>
|
||||
<el-col :span="12">
|
||||
<!-- 待签署的系统文件 -->
|
||||
<h3>{{ !isSigned ? $t('trials:workbench:title:sysDocBeSigned') : $t('trials:workbench:title:sysDocSigned') }}</h3>
|
||||
<h3>{{ !isSigned ? $t('trials:workbench:title:sysDocBeSigned') : $t('trials:workbench:title:sysDocSigned') }}
|
||||
</h3>
|
||||
</el-col>
|
||||
<el-col :span="12" style="text-align:right;">
|
||||
<h3>
|
||||
<Pagination class="page" :total="total" :page.sync="listQuery.pageIndex" :limit.sync="listQuery.pageSize" layout="total, sizes, prev, pager, next" :background="false" style="display: inline-block;" @pagination="getList" />
|
||||
<el-button icon="el-icon-refresh-left" size="small" circle :title="$t('common:button:reset')" @click="handleReset" />
|
||||
<Pagination class="page" :total="total" :page.sync="listQuery.pageIndex" :limit.sync="listQuery.pageSize"
|
||||
layout="total, sizes, prev, pager, next" :background="false" style="display: inline-block;"
|
||||
@pagination="getList" />
|
||||
<el-button icon="el-icon-refresh-left" size="small" circle :title="$t('common:button:reset')"
|
||||
@click="handleReset" />
|
||||
</h3>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<!-- -->
|
||||
<el-table
|
||||
ref="needSignSysList"
|
||||
v-loading="listLoading"
|
||||
:data="list"
|
||||
:show-header="true"
|
||||
v-adaptive="{bottomOffset:45}"
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
:default-sort ="{prop: 'UpdateTime', order: 'descending'}"
|
||||
>
|
||||
<el-table ref="needSignSysList" v-loading="listLoading" :data="list" :show-header="true"
|
||||
v-adaptive="{ bottomOffset: 45 }" height="100" @sort-change="handleSortByColumn"
|
||||
:default-sort="{ prop: 'UpdateTime', order: 'descending' }">
|
||||
<el-table-column type="index" width="40" />
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:fileType')"
|
||||
prop="FileType"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:fileName')"
|
||||
prop="Name"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:uploadTime')"
|
||||
prop="CreateTime"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('trials:sysDocBeSigned:table:ConfirmTime')"
|
||||
prop="ConfirmTime"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
width="140"
|
||||
>
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:fileType')" prop="FileType" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:fileName')" prop="Name" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:AttachmentCount')" prop="AttachmentCount"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">{{ scope.row.AttachmentCount
|
||||
}}</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:uploadTime')" prop="CreateTime" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:sysDocBeSigned:table:ConfirmTime')" prop="ConfirmTime" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('common:action:action')" width="140">
|
||||
<template slot-scope="scope">
|
||||
<!-- 预览 -->
|
||||
<el-button
|
||||
icon="el-icon-view"
|
||||
circle
|
||||
v-if="isSigned"
|
||||
:title="$t('trials:self-attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)"
|
||||
/>
|
||||
<el-button
|
||||
icon="el-icon-edit-outline"
|
||||
circle
|
||||
v-if="!isSigned"
|
||||
:title="$t('trials:needSignedSysDoc:action:sign')"
|
||||
@click="handleSign(scope.row)"
|
||||
/>
|
||||
<el-button icon="el-icon-view" circle v-if="isSigned" :title="$t('trials:self-attachment:action:preview')"
|
||||
@click="handlePreview(scope.row)" />
|
||||
<el-button icon="el-icon-edit-outline" circle v-if="!isSigned"
|
||||
:title="$t('trials:needSignedSysDoc:action:sign')" @click="handleSign(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<!-- 预览/签署文件 -->
|
||||
<el-dialog
|
||||
v-if="previewVisible"
|
||||
:visible.sync="previewVisible"
|
||||
:title="title"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="title" :fullscreen="true" append-to-body
|
||||
custom-class="base-dialog-wrapper">
|
||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
||||
$t('trials:sysDocBeSigned:table:AttachmentCount') }} ({{
|
||||
currentRow.AttachmentCount }})</span>
|
||||
<span v-if="!currentIsConfirm" style="position: fixed;right: 75px;top: 14px;">
|
||||
<span style="color:red;margin-right:10px;">
|
||||
<!-- 请仔细阅读文件,并签名确认 -->
|
||||
@@ -88,13 +61,8 @@
|
||||
<span v-show="duration < currentMinMinutes * 60">{{ `(${currentMinMinutes * 60 - duration}s)` }}</span>
|
||||
</span>
|
||||
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="timer !== null || duration === 0"
|
||||
:loading="btnLoading"
|
||||
@click="handleConfirm"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="timer !== null || duration === 0" :loading="btnLoading"
|
||||
@click="handleConfirm">
|
||||
{{ $t('common:button:sign') }}
|
||||
</el-button>
|
||||
</span>
|
||||
@@ -105,19 +73,19 @@
|
||||
</el-dialog>
|
||||
|
||||
<!-- 签名弹框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
append-to-body
|
||||
>
|
||||
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
|
||||
append-to-body>
|
||||
<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>
|
||||
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${currentUser})` }}</span>
|
||||
</div>
|
||||
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName" @closeDialog="closeSignDialog" />
|
||||
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName"
|
||||
@closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
||||
:isView="true" @getList="getList" />
|
||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible" :isView="true"
|
||||
v-if="perview_visible" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -125,6 +93,8 @@ import { getWaitSignSysDocList, setSystemDocFirstViewTime } from '@/api/trials'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import PreviewFile from '@/components/PreviewFile/index'
|
||||
import SignForm from '@/views/trials/trials-panel/attachments/self-attachment/components/SignForm'
|
||||
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
||||
import attachmentList from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentList'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
pageIndex: 1,
|
||||
@@ -135,7 +105,7 @@ const searchDataDefault = () => {
|
||||
}
|
||||
export default {
|
||||
name: 'NeedSignSysDoc',
|
||||
components: { Pagination, PreviewFile, SignForm },
|
||||
components: { Pagination, PreviewFile, SignForm, attachmentPreview, attachmentList },
|
||||
props: {
|
||||
isSigned: {
|
||||
type: Boolean,
|
||||
@@ -159,7 +129,14 @@ export default {
|
||||
currentType: '',
|
||||
currentIsConfirm: false,
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
currentRow: {}
|
||||
currentRow: {},
|
||||
perview_visible: false,
|
||||
SystemDocumentId: null,
|
||||
config: {
|
||||
visible: false,
|
||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
||||
width: '800px',
|
||||
},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -171,6 +148,16 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
openAttachment(row, isList = false) {
|
||||
if (!row.AttachmentCount) return false
|
||||
this.SystemDocumentId = row.Id
|
||||
this.currentRow = { ...row }
|
||||
if (!isList) {
|
||||
this.perview_visible = true
|
||||
} else {
|
||||
this.config.visible = true
|
||||
}
|
||||
},
|
||||
// 预览
|
||||
handlePreview(row) {
|
||||
this.currentRow = { ...row }
|
||||
@@ -270,8 +257,7 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.needSignSys-wrapper{
|
||||
.needSignSys-wrapper {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
@@ -370,7 +370,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div style="width: auto;flex:1;padding: 0 20px">
|
||||
<div style="width: auto;flex:1;padding: 0 20px;max-width: calc(100% - 250px);">
|
||||
<!-- 加急影像提交 -->
|
||||
<ImageSubmission v-if="selected === 'ImageSubmission'" :trial-id-list="trialIdList"
|
||||
:is-sign-system-doc="tabList.SysWaitSignDocCount > 0 && !isTestUser" />
|
||||
|
||||
@@ -12,8 +12,8 @@
|
||||
</style>
|
||||
<title></title>
|
||||
<!-- 引入外部JavaScript文件 -->
|
||||
<script type="text/javascript"
|
||||
src="https://onlyoffice.test.extimaging.com/web-apps/apps/api/documents/api.js"></script>
|
||||
<!-- <script type="text/javascript"
|
||||
src="https://onlyoffice.test.extimaging.com/web-apps/apps/api/documents/api.js"></script> -->
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@@ -28,22 +28,34 @@
|
||||
var arr = item.split('=')
|
||||
obj[arr[0]] = window.decodeURIComponent(arr[1])
|
||||
})
|
||||
var docEditor = new window.DocsAPI.DocEditor("placeholder", {
|
||||
type: "embedded",
|
||||
"document": {
|
||||
"fileType": obj.type,
|
||||
"key": "Khirz6zTPdfd7" + Date.now(),
|
||||
"title": obj.title,
|
||||
"url": url,
|
||||
},
|
||||
// editorConfig: {
|
||||
// lang:'zh'
|
||||
function loadScript() {
|
||||
return new Promise((resolve, reject) => {
|
||||
const script = document.createElement('script')
|
||||
script.src = `${obj.onlyOffice_url}/web-apps/apps/api/documents/api.js`
|
||||
script.onload = resolve
|
||||
script.onerror = reject
|
||||
document.head.appendChild(script)
|
||||
})
|
||||
}
|
||||
loadScript().then(() => {
|
||||
console.log('JS 加载完成')
|
||||
var docEditor = new window.DocsAPI.DocEditor("placeholder", {
|
||||
type: "embedded",
|
||||
"document": {
|
||||
"fileType": obj.type,
|
||||
"key": "Khirz6zTPdfd7" + Date.now(),
|
||||
"title": obj.title,
|
||||
"url": url,
|
||||
},
|
||||
// editorConfig: {
|
||||
// lang:'zh'
|
||||
|
||||
// },
|
||||
"documentType": obj.documentType,
|
||||
"height": "100%",
|
||||
// },
|
||||
"documentType": obj.documentType,
|
||||
"height": "100%",
|
||||
|
||||
});
|
||||
});
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ module.exports = defineConfig({
|
||||
]
|
||||
}),
|
||||
// new BundleAnalyzerPlugin(),
|
||||
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'prod' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
|
||||
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
|
||||
: new WebpackAliyunOss({
|
||||
from: ['./dist/**'],
|
||||
dist: process.env.VUE_APP_OSS_PATH + distDate,
|
||||
|
||||
Reference in New Issue
Block a user