Compare commits
No commits in common. "45e6a20988b84e9857fbdb598523738c8157044c" and "e0321bae7254d670dddda0299164243bad568758" have entirely different histories.
45e6a20988
...
e0321bae72
|
|
@ -5,8 +5,7 @@ NODE_ENV = 'development'
|
||||||
VUE_APP_BASE_PATH = '/'
|
VUE_APP_BASE_PATH = '/'
|
||||||
|
|
||||||
VUE_APP_IS_TEST = false
|
VUE_APP_IS_TEST = false
|
||||||
# onlyoffice地址
|
|
||||||
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
|
|
||||||
# base api
|
# base api
|
||||||
VUE_APP_BASE_API = 'http://123.56.94.154:7000'
|
VUE_APP_BASE_API = 'http://123.56.94.154:7000'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,6 @@ NODE_ENV = 'prod'
|
||||||
# base public path
|
# base public path
|
||||||
VUE_APP_BASE_PATH = '/'
|
VUE_APP_BASE_PATH = '/'
|
||||||
|
|
||||||
# onlyoffice地址
|
|
||||||
VUE_APP_ONLYOFFICE_URL = "https://office.extimaging.com"
|
|
||||||
|
|
||||||
# 是否开启登陆限制 true:是 false:否
|
# 是否开启登陆限制 true:是 false:否
|
||||||
VUE_APP_LOGIN_FOR_PERMISSION = true
|
VUE_APP_LOGIN_FOR_PERMISSION = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,8 +3,6 @@ ENV = 'production'
|
||||||
NODE_ENV = 'production'
|
NODE_ENV = 'production'
|
||||||
# base public path
|
# base public path
|
||||||
VUE_APP_BASE_PATH = '/'
|
VUE_APP_BASE_PATH = '/'
|
||||||
# onlyoffice地址
|
|
||||||
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
|
|
||||||
|
|
||||||
VUE_APP_IS_TEST = true
|
VUE_APP_IS_TEST = true
|
||||||
|
|
||||||
|
|
|
||||||
3
.env.uat
|
|
@ -4,9 +4,6 @@ NODE_ENV = 'production'
|
||||||
# base public path
|
# base public path
|
||||||
VUE_APP_BASE_PATH = '/'
|
VUE_APP_BASE_PATH = '/'
|
||||||
|
|
||||||
# onlyoffice地址
|
|
||||||
VUE_APP_ONLYOFFICE_URL = "https://onlyoffice.test.extimaging.com"
|
|
||||||
|
|
||||||
# base public path
|
# base public path
|
||||||
VUE_APP_BASE_PATH = '/'
|
VUE_APP_BASE_PATH = '/'
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -252,7 +252,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
handleSave() {
|
handleSave() {
|
||||||
this.$confirm(this.$t("i18n:confirm:updatei18n"))
|
this.$confirm('确定修改当前页面国际化内容?')
|
||||||
.then(() => {
|
.then(() => {
|
||||||
batchAddOrUpdateFrontInternationalization(this.tableData).then(
|
batchAddOrUpdateFrontInternationalization(this.tableData).then(
|
||||||
async (res) => {
|
async (res) => {
|
||||||
|
|
@ -270,7 +270,7 @@ export default {
|
||||||
i18n.mergeLocaleMessage('zh', zhMessages)
|
i18n.mergeLocaleMessage('zh', zhMessages)
|
||||||
i18n.mergeLocaleMessage('en', enMessages)
|
i18n.mergeLocaleMessage('en', enMessages)
|
||||||
this.drawer = false
|
this.drawer = false
|
||||||
this.$message.success(this.$t("i18n:message:updatei18nSuccessfully"))
|
this.$message.success('国际化修改成功')
|
||||||
if (this.il8nExternal) {
|
if (this.il8nExternal) {
|
||||||
this.$EventBus.$emit('il8nUpdate')
|
this.$EventBus.$emit('il8nUpdate')
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -212,20 +212,7 @@ export function getSystemDocumentList(param) {
|
||||||
data: 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) {
|
export function addOrUpdateSystemDocument(param) {
|
||||||
return request({
|
return request({
|
||||||
url: `/SystemDocument/addOrUpdateSystemDocument`,
|
url: `/SystemDocument/addOrUpdateSystemDocument`,
|
||||||
|
|
@ -233,29 +220,6 @@ export function addOrUpdateSystemDocument(param) {
|
||||||
data: param
|
data: param
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 新增/修改通用培训附件
|
|
||||||
export function addOrUpdateSystemDocumentAttachment(param) {
|
|
||||||
return request({
|
|
||||||
url: `/SystemDocument/addOrUpdateSystemDocumentAttachment`,
|
|
||||||
method: 'post',
|
|
||||||
data: param
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 通用培训附件列表
|
|
||||||
export function getSystemDocumentAttachmentList(param) {
|
|
||||||
return request({
|
|
||||||
url: `/SystemDocument/getSystemDocumentAttachmentList`,
|
|
||||||
method: 'post',
|
|
||||||
data: param
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 删除通用培训附件
|
|
||||||
export function deleteSystemDocumentAttachment(systemDocumentAttachmentId) {
|
|
||||||
return request({
|
|
||||||
url: `/SystemDocument/deleteSystemDocumentAttachment/${systemDocumentAttachmentId}`,
|
|
||||||
method: 'delete',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteSystemDocument(id) {
|
export function deleteSystemDocument(id) {
|
||||||
return request({
|
return request({
|
||||||
|
|
|
||||||
|
|
@ -178,15 +178,6 @@ export function pMTrainingRecordList_Export(data) {
|
||||||
data
|
data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 导出系统培训记录
|
|
||||||
export function getSysDocumentConfirmList_Export(data) {
|
|
||||||
return requestDownload({
|
|
||||||
url: `/ExcelExport/getSysDocumentConfirmList_Export`,
|
|
||||||
responseType: 'blob',
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 导出影像指控
|
// 导出影像指控
|
||||||
export function qCVisitList_Export(data) {
|
export function qCVisitList_Export(data) {
|
||||||
return requestDownload({
|
return requestDownload({
|
||||||
|
|
|
||||||
|
|
@ -1035,27 +1035,7 @@ export function getQCVisitList(param) {
|
||||||
data: param
|
data: param
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function getImageBackList(param) {
|
|
||||||
return request({
|
|
||||||
url: `/QCList/getImageBackList`,
|
|
||||||
method: 'post',
|
|
||||||
data: param
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function getImageBackApplyUserList(params) {
|
|
||||||
return request({
|
|
||||||
url: `/QCList/getImageBackApplyUserList`,
|
|
||||||
method: 'get',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function auditImageBack(params) {
|
|
||||||
return request({
|
|
||||||
url: `/QCOperation/auditImageBack`,
|
|
||||||
method: 'put',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function getQCChallengeList(param) {
|
export function getQCChallengeList(param) {
|
||||||
return request({
|
return request({
|
||||||
url: `/QCList/getQCChallengeList`,
|
url: `/QCList/getQCChallengeList`,
|
||||||
|
|
@ -1619,13 +1599,6 @@ export function getDocumentConfirmList(param) {
|
||||||
data: param
|
data: param
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function getSysDocumentConfirmList(param) {
|
|
||||||
return request({
|
|
||||||
url: `/TrialDocument/getSysDocumentConfirmList`,
|
|
||||||
method: 'post',
|
|
||||||
data: param
|
|
||||||
})
|
|
||||||
}
|
|
||||||
export function getTrialUserSelect(trialId) {
|
export function getTrialUserSelect(trialId) {
|
||||||
return request({
|
return request({
|
||||||
url: `/TrialDocument/getTrialUserSelect/${trialId}`,
|
url: `/TrialDocument/getTrialUserSelect/${trialId}`,
|
||||||
|
|
@ -1640,13 +1613,6 @@ export function getTrialDocAndSystemDocType(trialId) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSysDocSignUserList() {
|
|
||||||
return request({
|
|
||||||
url: `/TrialDocument/getSysDocSignUserList`,
|
|
||||||
method: 'get'
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateSubjectStatus(param) {
|
export function updateSubjectStatus(param) {
|
||||||
return request({
|
return request({
|
||||||
url: `/Subject/updateSubjectStatus`,
|
url: `/Subject/updateSubjectStatus`,
|
||||||
|
|
@ -3342,13 +3308,6 @@ export function getReReadingApplyToBeDoneList(param) {
|
||||||
data: param
|
data: param
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function getPMImageBackToBeDoneList(param) {
|
|
||||||
return request({
|
|
||||||
url: `/PersonalWorkstation/getPMImageBackToBeDoneList`,
|
|
||||||
method: 'post',
|
|
||||||
data: param
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteClinicalForm(param) {
|
export function deleteClinicalForm(param) {
|
||||||
return request({
|
return request({
|
||||||
|
|
@ -4036,91 +3995,3 @@ export function deleteTrialFileType(id) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 工作台-获取稽查文档
|
|
||||||
export function getAuditDocumentData(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/getAuditDocumentData`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-新增稽查文档
|
|
||||||
export function addAuditDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/addAuditDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-获取当前目录层级
|
|
||||||
export function getBreadcrumbData(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/getBreadcrumbData`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-修改稽查文档
|
|
||||||
export function updateAuditDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/updateAuditDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-删除稽查文档
|
|
||||||
export function deleteAuditDocument(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/deleteAuditDocument`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-稽查文档获取历史版本
|
|
||||||
export function getHistoricalVersion(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/getHistoricalVersion`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-稽查文档设置当前版本
|
|
||||||
export function setCurrentVersion(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/setCurrentVersion`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-稽查文档移动
|
|
||||||
export function movieFileOrFolder(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/movieFileOrFolder`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-稽查文档复制
|
|
||||||
export function copyFileOrFolder(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/copyFileOrFolder`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-稽查文档授权
|
|
||||||
export function setIsAuthorization(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/setIsAuthorization`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
// 工作台-稽查文档新增文件夹
|
|
||||||
export function addFolder(data) {
|
|
||||||
return request({
|
|
||||||
url: `/AuditDocument/addFolder`,
|
|
||||||
method: 'post',
|
|
||||||
data
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
@ -346,9 +346,9 @@ export function getReReadingOrBackInfluenceTaskList(taskId, isReReading, applyId
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function PMSetTaskBack(trialId, taskId, pmBackReason) {
|
export function PMSetTaskBack(trialId, taskId) {
|
||||||
return request({
|
return request({
|
||||||
url: `/VisitTask/PMSetTaskBack/${trialId}/${taskId}/${pmBackReason}`,
|
url: `/VisitTask/PMSetTaskBack/${trialId}/${taskId}`,
|
||||||
method: 'put'
|
method: 'put'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -287,12 +287,4 @@ export function forwardSVDicomImage(param) {
|
||||||
data: param
|
data: param
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// crc、iqc申请影像退回
|
|
||||||
export function requestImageBack(params) {
|
|
||||||
return request({
|
|
||||||
url: `/QCOperation/requestImageBack`,
|
|
||||||
method: 'put',
|
|
||||||
params
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -209,11 +209,3 @@ export function loginSelectUserRole(params) {
|
||||||
params,
|
params,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 忽略异地登录
|
|
||||||
export function setIsIgnoreUncommonly(data) {
|
|
||||||
return request({
|
|
||||||
url: `/User/setIsIgnoreUncommonly`,
|
|
||||||
method: 'post',
|
|
||||||
data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 175 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 22 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 665 B |
|
Before Width: | Height: | Size: 7.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB |
|
|
@ -1,28 +1,28 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="preview-wrapper">
|
<div class="preview-wrapper">
|
||||||
<iframe v-if="fileType.indexOf('jpg') !== -1 || fileType.indexOf('png') !== -1" frameborder="0" :src="filePath"
|
<iframe
|
||||||
width="100%" height="100%" />
|
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%"> -->
|
<!-- <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="filePath+'#toolbar=0'" width="100%" height="100%" frameborder="0" /> -->
|
||||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1"
|
<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" />
|
||||||
:src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`"
|
|
||||||
width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
|
||||||
<!-- <pdf-->
|
<!-- <pdf-->
|
||||||
<!-- v-else-if="fileType.indexOf('pdf') !== -1"-->
|
<!-- v-else-if="fileType.indexOf('pdf') !== -1"-->
|
||||||
<!-- :src="`/static/pdfjs/web/viewer.html?file=${filePath}`">-->
|
<!-- :src="`/static/pdfjs/web/viewer.html?file=${filePath}`">-->
|
||||||
<!-- </pdf>-->
|
<!-- </pdf>-->
|
||||||
<iframe v-else
|
<div 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') }}
|
{{ $t('common:message:downloadFile') }}
|
||||||
<el-link type="primary" @click="downLoadFile">{{ $t('common:button:download') }}</el-link>
|
<el-link type="primary" @click="downLoadFile">{{ $t('common:button:download') }}</el-link>
|
||||||
</div> -->
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { mapGetters } from 'vuex'
|
import { mapGetters } from 'vuex'
|
||||||
import DOCUMENTTYPE from "@/utils/onlyOffice_type.js"
|
|
||||||
export default {
|
export default {
|
||||||
name: 'PreviewFile',
|
name: 'PreviewFile',
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -36,23 +36,12 @@ export default {
|
||||||
fileType: {
|
fileType: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
}
|
||||||
title: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentUser: zzSessionStorage.getItem('userName'),
|
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() {
|
mounted() {
|
||||||
|
|
@ -73,16 +62,14 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.preview-wrapper {
|
.preview-wrapper{
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width:100%;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
::-webkit-scrollbar {
|
||||||
width: 7px;
|
width: 7px;
|
||||||
height: 7px;
|
height: 7px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
::-webkit-scrollbar-thumb {
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background: #d0d0d0;
|
background: #d0d0d0;
|
||||||
|
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
||||||
import Vue from "vue";
|
|
||||||
import OnlyOffice from "./index.vue";
|
|
||||||
|
|
||||||
const PreviewConstructor = Vue.extend(OnlyOffice);
|
|
||||||
|
|
||||||
const onlyOffice = options => {
|
|
||||||
const { path, type, title } = options;
|
|
||||||
if (!path) throw `path is requred.but ${path}`
|
|
||||||
const id = `OnlyOffice_${new Date().getTime()}`;
|
|
||||||
const instance = new PreviewConstructor();
|
|
||||||
instance.id = id;
|
|
||||||
instance.vm = instance.$mount();
|
|
||||||
if (instance.vm.visible) return;
|
|
||||||
document.body.appendChild(instance.vm.$el);
|
|
||||||
instance.vm.open(path, type, title);
|
|
||||||
instance.vm.$on("closed", () => {
|
|
||||||
instance.vm.docEditor = null
|
|
||||||
document.body.removeChild(instance.vm.$el);
|
|
||||||
instance.vm.$destroy();
|
|
||||||
});
|
|
||||||
return instance.vm;
|
|
||||||
}
|
|
||||||
export default onlyOffice;
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
import OnlyOffice from "./index.vue";
|
|
||||||
import onlyOffice from "./fun";
|
|
||||||
|
|
||||||
export default Vue => {
|
|
||||||
Vue.component(OnlyOffice.name, OnlyOffice);
|
|
||||||
Vue.prototype.$onlyOffice = onlyOffice;
|
|
||||||
};
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog v-if="visible" :visible.sync="visible" :title="title" :fullscreen="true" append-to-body
|
|
||||||
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}?onlyOffice_url=${onlyOffice_url}&type=${type}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
|
|
||||||
width="100%" height="99%" frameborder="0" crossorigin="anonymous" />
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import DOCUMENTTYPE from "@/utils/onlyOffice_type.js"
|
|
||||||
export default {
|
|
||||||
name: "OnlyOffice",
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
path: null,
|
|
||||||
type: null,
|
|
||||||
title: null,
|
|
||||||
documentType: null,
|
|
||||||
currentUser: zzSessionStorage.getItem('userName'),
|
|
||||||
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL
|
|
||||||
};
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
|
|
||||||
open(path, type, title) {
|
|
||||||
this.path = path;
|
|
||||||
this.type = type.toLowerCase();
|
|
||||||
this.documentType = DOCUMENTTYPE[`.${this.type}`]
|
|
||||||
this.title = title;
|
|
||||||
this.visible = true;
|
|
||||||
},
|
|
||||||
handleClose() {
|
|
||||||
this.$emit("closed");
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
#placeholder {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -8,25 +8,61 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--检查列表-->
|
<!--检查列表-->
|
||||||
<el-table :data="list" style="width: 100%" v-adaptive="{ bottomOffset: 60 }" :loading="loading"
|
<el-table
|
||||||
@sort-change="handleSortByColumn" :default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
:data="list"
|
||||||
|
style="width: 100%"
|
||||||
|
v-adaptive="{ bottomOffset: 60 }"
|
||||||
|
:loading="loading"
|
||||||
|
@sort-change="handleSortByColumn"
|
||||||
|
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }"
|
||||||
|
>
|
||||||
<!--受试者-->
|
<!--受试者-->
|
||||||
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')" />
|
<el-table-column
|
||||||
|
prop="SubjectCode"
|
||||||
|
:label="$t('upload:nonedicom:table:subject')"
|
||||||
|
/>
|
||||||
<!--任务名称-->
|
<!--任务名称-->
|
||||||
<el-table-column prop="TaskBlindName" :label="$t('upload:nonedicom:table:taskName')" sortable="custom" />
|
<el-table-column
|
||||||
|
prop="TaskBlindName"
|
||||||
|
:label="$t('upload:nonedicom:table:taskName')"
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<!--检查类型-->
|
<!--检查类型-->
|
||||||
<el-table-column prop="Modality" :label="$t('upload:nonedicom:table:molityType')" sortable="custom">
|
<el-table-column
|
||||||
|
prop="Modality"
|
||||||
|
:label="$t('upload:nonedicom:table:molityType')"
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!--检查部位-->
|
<!--检查部位-->
|
||||||
<el-table-column prop="BodyPart" :label="$t('upload:nonedicom:table:bodyPart')" sortable="custom" />
|
<el-table-column
|
||||||
|
prop="BodyPart"
|
||||||
|
:label="$t('upload:nonedicom:table:bodyPart')"
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<!--原文件数-->
|
<!--原文件数-->
|
||||||
<el-table-column prop="FileCount" :label="$t('upload:nonedicom:table:fileCount')">
|
<el-table-column
|
||||||
|
prop="FileCount"
|
||||||
|
:label="$t('upload:nonedicom:table:fileCount')"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-popover v-if="scope.row.FileCount" trigger="click" placement="bottom">
|
<el-popover
|
||||||
|
v-if="scope.row.FileCount"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom"
|
||||||
|
>
|
||||||
<el-table :data="scope.row.FileList" height="300" size="small">
|
<el-table :data="scope.row.FileList" height="300" size="small">
|
||||||
<!-- 文件名称 -->
|
<!-- 文件名称 -->
|
||||||
<el-table-column prop="FileName" :label="$t('trials:audit:table:nonDicomsFileName')" width="200" />
|
<el-table-column
|
||||||
<el-table-column prop="FileSize" :label="$t('trials:audit:table:nonDicomsFileSize')" width="100">
|
prop="FileName"
|
||||||
|
:label="$t('trials:audit:table:nonDicomsFileName')"
|
||||||
|
width="200"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="FileSize"
|
||||||
|
:label="$t('trials:audit:table:nonDicomsFileSize')"
|
||||||
|
width="100"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{
|
<span>{{
|
||||||
scope.row.FileSize && scope.row.FileSize > 0
|
scope.row.FileSize && scope.row.FileSize > 0
|
||||||
|
|
@ -38,13 +74,27 @@
|
||||||
<el-table-column :label="$t('common:action:action')" width="120">
|
<el-table-column :label="$t('common:action:action')" width="120">
|
||||||
<template slot-scope="files">
|
<template slot-scope="files">
|
||||||
<!-- 预览 -->
|
<!-- 预览 -->
|
||||||
<viewer :ref="files.row.Path" style="margin: 0 10px"
|
<viewer
|
||||||
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]">
|
:ref="files.row.Path"
|
||||||
<el-button circle icon="el-icon-view" :title="$t('upload:nonedicom:button:preview')" :disabled="files.row.FileType &&
|
style="margin: 0 10px"
|
||||||
files.row.FileType.indexOf('zip') >= 0
|
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]"
|
||||||
" @click.native.prevent="previewFile(files.row)" />
|
>
|
||||||
<img v-show="false" crossorigin="anonymous" :src="`${OSSclientConfig.basePath}${files.row.Path}`"
|
<el-button
|
||||||
alt="Image" />
|
circle
|
||||||
|
icon="el-icon-view"
|
||||||
|
:title="$t('upload:nonedicom:button:preview')"
|
||||||
|
:disabled="
|
||||||
|
files.row.FileType &&
|
||||||
|
files.row.FileType.indexOf('zip') >= 0
|
||||||
|
"
|
||||||
|
@click.native.prevent="previewFile(files.row)"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
v-show="false"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
:src="`${OSSclientConfig.basePath}${files.row.Path}`"
|
||||||
|
alt="Image"
|
||||||
|
/>
|
||||||
</viewer>
|
</viewer>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
@ -59,13 +109,32 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!--后处理文件数-->
|
<!--后处理文件数-->
|
||||||
<el-table-column prop="UploadedFileCount" :label="$t('upload:nonedicom:table:uploadFileCount')">
|
<el-table-column
|
||||||
|
prop="UploadedFileCount"
|
||||||
|
:label="$t('upload:nonedicom:table:uploadFileCount')"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-popover v-if="scope.row.UploadedFileCount" trigger="click" placement="bottom">
|
<el-popover
|
||||||
<el-table :data="scope.row.UploadedFileList" height="300" size="small">
|
v-if="scope.row.UploadedFileCount"
|
||||||
|
trigger="click"
|
||||||
|
placement="bottom"
|
||||||
|
>
|
||||||
|
<el-table
|
||||||
|
:data="scope.row.UploadedFileList"
|
||||||
|
height="300"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
<!-- 文件名称 -->
|
<!-- 文件名称 -->
|
||||||
<el-table-column prop="FileName" :label="$t('trials:audit:table:nonDicomsFileName')" width="200" />
|
<el-table-column
|
||||||
<el-table-column prop="FileSize" :label="$t('trials:audit:table:nonDicomsFileSize')" width="100">
|
prop="FileName"
|
||||||
|
:label="$t('trials:audit:table:nonDicomsFileName')"
|
||||||
|
width="200"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="FileSize"
|
||||||
|
:label="$t('trials:audit:table:nonDicomsFileSize')"
|
||||||
|
width="100"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{
|
<span>{{
|
||||||
scope.row.FileSize && scope.row.FileSize > 0
|
scope.row.FileSize && scope.row.FileSize > 0
|
||||||
|
|
@ -77,13 +146,27 @@
|
||||||
<el-table-column :label="$t('common:action:action')" width="120">
|
<el-table-column :label="$t('common:action:action')" width="120">
|
||||||
<template slot-scope="files">
|
<template slot-scope="files">
|
||||||
<!-- 预览 -->
|
<!-- 预览 -->
|
||||||
<viewer :ref="files.row.Path" style="margin: 0 10px"
|
<viewer
|
||||||
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]">
|
:ref="files.row.Path"
|
||||||
<el-button circle icon="el-icon-view" :title="$t('upload:nonedicom:button:preview')" :disabled="files.row.FileType &&
|
style="margin: 0 10px"
|
||||||
files.row.FileType.indexOf('zip') >= 0
|
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]"
|
||||||
" @click.native.prevent="previewFile(files.row)" />
|
>
|
||||||
<img v-show="false" crossorigin="anonymous" :src="`${OSSclientConfig.basePath}${files.row.Path}`"
|
<el-button
|
||||||
alt="Image" />
|
circle
|
||||||
|
icon="el-icon-view"
|
||||||
|
:title="$t('upload:nonedicom:button:preview')"
|
||||||
|
:disabled="
|
||||||
|
files.row.FileType &&
|
||||||
|
files.row.FileType.indexOf('zip') >= 0
|
||||||
|
"
|
||||||
|
@click.native.prevent="previewFile(files.row)"
|
||||||
|
/>
|
||||||
|
<img
|
||||||
|
v-show="false"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
:src="`${OSSclientConfig.basePath}${files.row.Path}`"
|
||||||
|
alt="Image"
|
||||||
|
/>
|
||||||
</viewer>
|
</viewer>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
@ -97,34 +180,75 @@
|
||||||
<span v-else>{{ scope.row.UploadedFileCount }}</span>
|
<span v-else>{{ scope.row.UploadedFileCount }}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('common:action:action')" fixed="right" width="180">
|
<el-table-column
|
||||||
|
:label="$t('common:action:action')"
|
||||||
|
fixed="right"
|
||||||
|
width="180"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!--预览--->
|
<!--预览--->
|
||||||
<el-button circle :disabled="scope.row.UploadedFileCount <= 0" icon="el-icon-view"
|
<el-button
|
||||||
:title="$t('upload:nonedicom:button:preview')" @click.stop="handlePreviewNoneDicomFiles(scope.row)" />
|
circle
|
||||||
|
:disabled="scope.row.UploadedFileCount <= 0"
|
||||||
|
icon="el-icon-view"
|
||||||
|
:title="$t('upload:nonedicom:button:preview')"
|
||||||
|
@click.stop="handlePreviewNoneDicomFiles(scope.row)"
|
||||||
|
/>
|
||||||
<!--上传--->
|
<!--上传--->
|
||||||
<el-button circle icon="el-icon-upload2" :title="$t('upload:nonedicom:button:upload')"
|
<el-button
|
||||||
@click.native.prevent="handleUpload(scope.row)" />
|
circle
|
||||||
|
icon="el-icon-upload2"
|
||||||
|
:title="$t('upload:nonedicom:button:upload')"
|
||||||
|
@click.native.prevent="handleUpload(scope.row)"
|
||||||
|
/>
|
||||||
<!--删除--->
|
<!--删除--->
|
||||||
<el-button :disabled="scope.row.UploadedFileCount <= 0 ||
|
<el-button
|
||||||
scope.row.ReadingTaskState === 2
|
:disabled="
|
||||||
" circle icon="el-icon-delete" :title="$t('upload:nonedicom:button:delete')"
|
scope.row.UploadedFileCount <= 0 ||
|
||||||
@click.stop="remove(scope.row)" />
|
scope.row.ReadingTaskState === 2
|
||||||
|
"
|
||||||
|
circle
|
||||||
|
icon="el-icon-delete"
|
||||||
|
:title="$t('upload:nonedicom:button:delete')"
|
||||||
|
@click.stop="remove(scope.row)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<!-- 预览单个图像 -->
|
<!-- 预览单个图像 -->
|
||||||
<el-dialog v-if="imgObj.visible" :visible.sync="imgObj.visible" :title="$t('upload:nonedicom:dialogTitle:preview')"
|
<el-dialog
|
||||||
append-to-body width="565px">
|
v-if="imgObj.visible"
|
||||||
<div v-loading="imgObj.loading" class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
:visible.sync="imgObj.visible"
|
||||||
<el-image :src="`${OSSclientConfig.basePath}${imgObj.url}`" crossorigin="anonymous" fit="fit"
|
:title="$t('upload:nonedicom:dialogTitle:preview')"
|
||||||
style="height: 500px; width: 500px" @error="imgObj.loading = false" @load="imgObj.loading = false" />
|
append-to-body
|
||||||
|
width="565px"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-loading="imgObj.loading"
|
||||||
|
class="base-modal-body"
|
||||||
|
style="border: 2px solid #ccc; padding: 10px"
|
||||||
|
>
|
||||||
|
<el-image
|
||||||
|
:src="`${OSSclientConfig.basePath}${imgObj.url}`"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
fit="fit"
|
||||||
|
style="height: 500px; width: 500px"
|
||||||
|
@error="imgObj.loading = false"
|
||||||
|
@load="imgObj.loading = false"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- 上传非dicom文件 -->
|
<!-- 上传非dicom文件 -->
|
||||||
<el-dialog v-if="uploadVisible" :visible.sync="uploadVisible" :close-on-click-modal="false"
|
<el-dialog
|
||||||
:title="$t('trials:uploadNonDicoms:dialogTitle:upload')" width="800px" append-to-body
|
v-if="uploadVisible"
|
||||||
custom-class="base-dialog-wrapper" @close="resetFileDiaolg">
|
:visible.sync="uploadVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:title="$t('trials:uploadNonDicoms:dialogTitle:upload')"
|
||||||
|
width="800px"
|
||||||
|
append-to-body
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
@close="resetFileDiaolg"
|
||||||
|
>
|
||||||
<!-- 多文件上传 -->
|
<!-- 多文件上传 -->
|
||||||
<form id="inputForm" ref="uploadForm">
|
<form id="inputForm" ref="uploadForm">
|
||||||
<el-divider content-position="left">{{
|
<el-divider content-position="left">{{
|
||||||
|
|
@ -132,15 +256,33 @@
|
||||||
}}</el-divider>
|
}}</el-divider>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="upload" style="margin-right: 10px">
|
<div class="upload" style="margin-right: 10px">
|
||||||
<input multiple="multiple" webkitdirectory="" directory accept="*/*" type="file" name="uploadFolder"
|
<input
|
||||||
class="select-file" title="" @change="beginScanFiles($event)" v-if="!btnLoading" />
|
multiple="multiple"
|
||||||
|
webkitdirectory=""
|
||||||
|
directory
|
||||||
|
accept="*/*"
|
||||||
|
type="file"
|
||||||
|
name="uploadFolder"
|
||||||
|
class="select-file"
|
||||||
|
title=""
|
||||||
|
@change="beginScanFiles($event)"
|
||||||
|
v-if="!btnLoading"
|
||||||
|
/>
|
||||||
<div class="btn-select">
|
<div class="btn-select">
|
||||||
{{ $t('trials:uploadNonDicoms:button:selectFolder') }}
|
{{ $t('trials:uploadNonDicoms:button:selectFolder') }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="upload">
|
<div class="upload">
|
||||||
<input class="select-file" multiple="" :accept="faccept.join(',')" type="file" name="uploadFile" title=""
|
<input
|
||||||
@change="beginScanFiles($event)" v-if="!btnLoading" />
|
class="select-file"
|
||||||
|
multiple=""
|
||||||
|
:accept="faccept.join(',')"
|
||||||
|
type="file"
|
||||||
|
name="uploadFile"
|
||||||
|
title=""
|
||||||
|
@change="beginScanFiles($event)"
|
||||||
|
v-if="!btnLoading"
|
||||||
|
/>
|
||||||
<div class="btn-select">
|
<div class="btn-select">
|
||||||
{{ $t('trials:uploadNonDicoms:button:select') }}
|
{{ $t('trials:uploadNonDicoms:button:select') }}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -151,46 +293,82 @@
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
<!-- 文件列表 -->
|
<!-- 文件列表 -->
|
||||||
<el-table ref="filesTable" :data="fileList" class="dicomFiles-table" height="300"
|
<el-table
|
||||||
@selection-change="handleSelectionChange">
|
ref="filesTable"
|
||||||
<el-table-column type="selection" width="55" :selectable="(row, index) => row.status !== 2 && !btnLoading" />
|
:data="fileList"
|
||||||
|
class="dicomFiles-table"
|
||||||
|
height="300"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
>
|
||||||
|
<el-table-column
|
||||||
|
type="selection"
|
||||||
|
width="55"
|
||||||
|
:selectable="(row, index) => row.status !== 2 && !btnLoading"
|
||||||
|
/>
|
||||||
<el-table-column type="index" width="50" />
|
<el-table-column type="index" width="50" />
|
||||||
<!-- 文件名称 -->
|
<!-- 文件名称 -->
|
||||||
<el-table-column prop="name" :label="$t('trials:uploadNonDicoms:table:fileName')" min-width="100" />
|
<el-table-column
|
||||||
|
prop="name"
|
||||||
|
:label="$t('trials:uploadNonDicoms:table:fileName')"
|
||||||
|
min-width="100"
|
||||||
|
/>
|
||||||
<!-- 文件大小 -->
|
<!-- 文件大小 -->
|
||||||
<el-table-column prop="size" :label="$t('trials:uploadNonDicoms:table:fileSize')">
|
<el-table-column
|
||||||
|
prop="size"
|
||||||
|
:label="$t('trials:uploadNonDicoms:table:fileSize')"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{
|
<span>{{
|
||||||
scope.row.size && scope.row.size > 0
|
scope.row.size && scope.row.size > 0
|
||||||
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
|
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
|
||||||
: '0MB'
|
: ''
|
||||||
}}</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 文件类型 -->
|
<!-- 文件类型 -->
|
||||||
<el-table-column prop="type" :label="$t('trials:uploadNonDicoms:table:fileType')" />
|
<el-table-column
|
||||||
|
prop="type"
|
||||||
|
:label="$t('trials:uploadNonDicoms:table:fileType')"
|
||||||
|
/>
|
||||||
<!-- 上传状态 -->
|
<!-- 上传状态 -->
|
||||||
<el-table-column prop="status" :label="$t('trials:uploadNonDicoms:table:uploadStatus')" min-width="100">
|
<el-table-column
|
||||||
|
prop="status"
|
||||||
|
:label="$t('trials:uploadNonDicoms:table:uploadStatus')"
|
||||||
|
min-width="100"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="['warning', 'info', 'success', 'danger'][scope.row.status]"
|
<el-tag
|
||||||
v-if="scope.row.status || scope.row.status === 0">{{ $fd('NoneDicomUploadStatus', scope.row.status) }}
|
:type="['warning', 'info', 'success', 'danger'][scope.row.status]"
|
||||||
|
v-if="scope.row.status || scope.row.status === 0"
|
||||||
|
>{{ $fd('NoneDicomUploadStatus', scope.row.status) }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('trials:uploadNonDicoms:table:failedFileCount')" min-width="150"
|
<el-table-column
|
||||||
show-overflow-tooltip>
|
:label="$t('trials:uploadNonDicoms:table:failedFileCount')"
|
||||||
|
min-width="150"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<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) *
|
<el-progress
|
||||||
1
|
color="#409eff"
|
||||||
: ((scope.row.uploadFileSize * 100) / 1).toFixed(2) *
|
:percentage="
|
||||||
1
|
((scope.row.uploadFileSize * 100) / scope.row.size).toFixed(2) *
|
||||||
" />
|
1
|
||||||
|
"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('common:action:action')">
|
<el-table-column :label="$t('common:action:action')">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button size="mini" icon="el-icon-delete" circle :disabled="btnLoading"
|
<el-button
|
||||||
:title="$t('trials:crcUpload:action:delete')" @click="handleRemoveFile(scope.row)" />
|
size="mini"
|
||||||
|
icon="el-icon-delete"
|
||||||
|
circle
|
||||||
|
:disabled="btnLoading"
|
||||||
|
:title="$t('trials:crcUpload:action:delete')"
|
||||||
|
@click="handleRemoveFile(scope.row)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -198,8 +376,13 @@
|
||||||
<span style="margin-right: 10px">{{
|
<span style="margin-right: 10px">{{
|
||||||
$store.state.trials.uploadTip
|
$store.state.trials.uploadTip
|
||||||
}}</span>
|
}}</span>
|
||||||
<el-button size="small" type="primary" :disabled="selectArr.length == 0" :loading="btnLoading"
|
<el-button
|
||||||
@click="beginUpload">
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="selectArr.length == 0"
|
||||||
|
:loading="btnLoading"
|
||||||
|
@click="beginUpload"
|
||||||
|
>
|
||||||
{{ $t('trials:uploadNonDicoms:action:upload') }}
|
{{ $t('trials:uploadNonDicoms:action:upload') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -405,7 +588,7 @@ export default {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(() => { })
|
.catch(() => {})
|
||||||
},
|
},
|
||||||
resetUploadForm() {
|
resetUploadForm() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
|
|
@ -531,10 +714,11 @@ export default {
|
||||||
if (!this.uploadVisible) return
|
if (!this.uploadVisible) return
|
||||||
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
||||||
file.status = 1
|
file.status = 1
|
||||||
let path = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId
|
let path = `/${this.$route.query.trialId}/TaskImage/${
|
||||||
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
|
this.currentRow.SubjectId
|
||||||
.substring(file.name.lastIndexOf('.'))
|
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
|
||||||
.toLocaleLowerCase()}`
|
.substring(file.name.lastIndexOf('.'))
|
||||||
|
.toLocaleLowerCase()}`
|
||||||
file.curPath = path
|
file.curPath = path
|
||||||
const fileData = await this.fileToBlob(file.file)
|
const fileData = await this.fileToBlob(file.file)
|
||||||
let res = await this.fileToOss(path, fileData, file)
|
let res = await this.fileToOss(path, fileData, file)
|
||||||
|
|
@ -588,7 +772,7 @@ export default {
|
||||||
(percentage, checkpoint, lastPer) => {
|
(percentage, checkpoint, lastPer) => {
|
||||||
item.uploadFileSize += checkpoint.size * (percentage - lastPer)
|
item.uploadFileSize += checkpoint.size * (percentage - lastPer)
|
||||||
if (item.uploadFileSize > file.fileSize) {
|
if (item.uploadFileSize > file.fileSize) {
|
||||||
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
item.uploadFileSize = file.fileSize
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
@ -685,7 +869,6 @@ export default {
|
||||||
.top {
|
.top {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload {
|
.upload {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: 30px;
|
height: 30px;
|
||||||
|
|
@ -700,7 +883,6 @@ export default {
|
||||||
background: #428bca;
|
background: #428bca;
|
||||||
border-color: #428bca;
|
border-color: #428bca;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
||||||
.select-file {
|
.select-file {
|
||||||
height: 30px;
|
height: 30px;
|
||||||
width: 90px;
|
width: 90px;
|
||||||
|
|
@ -711,7 +893,6 @@ export default {
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
font-size: 0;
|
font-size: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-select {
|
.btn-select {
|
||||||
//给显示在页面上的按钮写样式
|
//给显示在页面上的按钮写样式
|
||||||
width: 90px;
|
width: 90px;
|
||||||
|
|
@ -727,12 +908,10 @@ export default {
|
||||||
pointer-events: none; //pointer-events:none用来控制该标签的点击穿透事件
|
pointer-events: none; //pointer-events:none用来控制该标签的点击穿透事件
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.tip {
|
.tip {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
margin: 3px 5px 0 0;
|
margin: 3px 5px 0 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
Before Width: | Height: | Size: 26 KiB |
|
|
@ -54,8 +54,6 @@ import upload from '@/components/element-ui/upload'
|
||||||
Vue.use(upload)
|
Vue.use(upload)
|
||||||
import Preview from '@/components/Preview/index'
|
import Preview from '@/components/Preview/index'
|
||||||
Vue.use(Preview)
|
Vue.use(Preview)
|
||||||
import Onlyoffice from '@/components/Preview_onlyoffice/index'
|
|
||||||
Vue.use(Onlyoffice)
|
|
||||||
import MFA from '@/components/MFA/index'
|
import MFA from '@/components/MFA/index'
|
||||||
Vue.use(MFA)
|
Vue.use(MFA)
|
||||||
import FB from '@/components/feedBack/index'
|
import FB from '@/components/feedBack/index'
|
||||||
|
|
@ -310,11 +308,6 @@ async function VueInit() {
|
||||||
text = text.replace(test, item.TrialName)
|
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 i18n.t(key)
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -68,12 +68,6 @@ body .el-table th.gutter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-ellipsis {
|
|
||||||
overflow: hidden;
|
|
||||||
white-space: nowrap;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.el-loading-mask {
|
.el-loading-mask {
|
||||||
background-color: rgba(255, 255, 255, 0.5);
|
background-color: rgba(255, 255, 255, 0.5);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,66 +0,0 @@
|
||||||
let TYPES = ['word', 'cell', 'slide', 'pdf']
|
|
||||||
|
|
||||||
let DOCUMENTTYPE = {
|
|
||||||
'.doc': TYPES[0],
|
|
||||||
'.docm': TYPES[0],
|
|
||||||
'.docx': TYPES[0],
|
|
||||||
'.dot': TYPES[0],
|
|
||||||
'.dotm': TYPES[0],
|
|
||||||
'.dotx': TYPES[0],
|
|
||||||
'.epub': TYPES[0],
|
|
||||||
'.fb2': TYPES[0],
|
|
||||||
'.fodt': TYPES[0],
|
|
||||||
'.htm': TYPES[0],
|
|
||||||
'.html': TYPES[0],
|
|
||||||
'.mht': TYPES[0],
|
|
||||||
'.mhtml': TYPES[0],
|
|
||||||
'.odt': TYPES[0],
|
|
||||||
'.ott': TYPES[0],
|
|
||||||
'.pages': TYPES[0],
|
|
||||||
'.rtf': TYPES[0],
|
|
||||||
'.stw': TYPES[0],
|
|
||||||
'.sxw': TYPES[0],
|
|
||||||
'.txt': TYPES[0],
|
|
||||||
'.wps': TYPES[0],
|
|
||||||
'.wpt': TYPES[0],
|
|
||||||
'.xml': TYPES[0],
|
|
||||||
'.csv': TYPES[1],
|
|
||||||
'.et': TYPES[1],
|
|
||||||
'.ett': TYPES[1],
|
|
||||||
'.fods': TYPES[1],
|
|
||||||
'.numbers': TYPES[1],
|
|
||||||
'.ods': TYPES[1],
|
|
||||||
'.ots': TYPES[1],
|
|
||||||
'.sxc': TYPES[1],
|
|
||||||
'.xls': TYPES[1],
|
|
||||||
'.xlsb': TYPES[1],
|
|
||||||
'.xlsm': TYPES[1],
|
|
||||||
'.xlsx': TYPES[1],
|
|
||||||
'.xlt': TYPES[1],
|
|
||||||
'.xltm': TYPES[1],
|
|
||||||
'.xltx': TYPES[1],
|
|
||||||
'.xml': TYPES[1],
|
|
||||||
'.dps': TYPES[2],
|
|
||||||
'.dpt': TYPES[2],
|
|
||||||
'.fodp': TYPES[2],
|
|
||||||
'.key': TYPES[2],
|
|
||||||
'.odp': TYPES[2],
|
|
||||||
'.otp': TYPES[2],
|
|
||||||
'.pot': TYPES[2],
|
|
||||||
'.potm': TYPES[2],
|
|
||||||
'.potx': TYPES[2],
|
|
||||||
'.pps': TYPES[2],
|
|
||||||
'.ppsm': TYPES[2],
|
|
||||||
'.ppsx': TYPES[2],
|
|
||||||
'.ppt': TYPES[2],
|
|
||||||
'.pptm': TYPES[2],
|
|
||||||
'.pptx': TYPES[2],
|
|
||||||
'.sxi': TYPES[2],
|
|
||||||
'.djvu': TYPES[3],
|
|
||||||
'.docxf': TYPES[3],
|
|
||||||
'.oform': TYPES[3],
|
|
||||||
'.oxps': TYPES[3],
|
|
||||||
'.pdf': TYPES[3],
|
|
||||||
'.xps': TYPES[3]
|
|
||||||
}
|
|
||||||
export default DOCUMENTTYPE
|
|
||||||
|
|
@ -21,8 +21,6 @@ service.interceptors.request.use(
|
||||||
async config => {
|
async config => {
|
||||||
path = router && router.app && router.app._route && router.app._route.path
|
path = router && router.app && router.app._route && router.app._route.path
|
||||||
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
||||||
// 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')
|
var language = zzSessionStorage.getItem('lang')
|
||||||
config.headers['Accept-Language'] = language === 'en' ? 'en-US,en;q=0.5' : 'zh-CN,zh;q=0.9'
|
config.headers['Accept-Language'] = language === 'en' ? 'en-US,en;q=0.5' : 'zh-CN,zh;q=0.9'
|
||||||
config.headers['TimeZoneId'] = moment.tz.guess()
|
config.headers['TimeZoneId'] = moment.tz.guess()
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,100 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form ref="sysAttachmentFrom" v-loading="loading" :model="form" label-width="190px" size="small" :rules="rules"
|
<el-form
|
||||||
class="upload-temporary-file">
|
ref="sysAttachmentFrom"
|
||||||
|
v-loading="loading"
|
||||||
|
:model="form"
|
||||||
|
label-width="190px"
|
||||||
|
size="small"
|
||||||
|
:rules="rules"
|
||||||
|
class="upload-temporary-file"
|
||||||
|
>
|
||||||
<div class="base-dialog-body">
|
<div class="base-dialog-body">
|
||||||
<el-form-item :label="$t('dictionary:signature:form:FileTypeId')" prop="FileTypeId">
|
<el-form-item
|
||||||
<el-select v-model="form.FileTypeId" style="width: 100%" size="small" filterable>
|
:label="$t('dictionary:signature:form:FileTypeId')"
|
||||||
<el-option v-for="item of dictionaryList.Sys_Document" :key="item.Id" :label="item.Value" :value="item.Id" />
|
prop="FileTypeId"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="form.FileTypeId"
|
||||||
|
style="width: 100%"
|
||||||
|
size="small"
|
||||||
|
filterable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of dictionaryList.Sys_Document"
|
||||||
|
:key="item.Id"
|
||||||
|
:label="item.Value"
|
||||||
|
:value="item.Id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item :label="$t('dictionary:signature:form:File')">
|
<el-form-item :label="$t('dictionary:signature:form:File')">
|
||||||
<div class="upload-container">
|
<div class="upload-container">
|
||||||
<el-upload class="upload-demo" action accept=".pdf" :before-upload="beforeUpload"
|
<el-upload
|
||||||
:http-request="handleUploadFile" :on-preview="handlePreview" :on-remove="handleRemoveFile"
|
class="upload-demo"
|
||||||
:show-file-list="true" :file-list="fileList" :limit="1" :on-exceed="handleExceed"
|
action
|
||||||
:disabled="form.Type === ''">
|
accept=".pdf"
|
||||||
<el-button size="small" type="primary" :disabled="form.FileTypeId === ''" :loading="btnLoading">{{
|
:before-upload="beforeUpload"
|
||||||
$t('common:button:check') }}</el-button>
|
:http-request="handleUploadFile"
|
||||||
|
:on-preview="handlePreview"
|
||||||
|
:on-remove="handleRemoveFile"
|
||||||
|
:show-file-list="true"
|
||||||
|
:file-list="fileList"
|
||||||
|
:limit="1"
|
||||||
|
:on-exceed="handleExceed"
|
||||||
|
:disabled="form.Type === ''"
|
||||||
|
>
|
||||||
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="form.FileTypeId === ''"
|
||||||
|
:loading="btnLoading"
|
||||||
|
>{{ $t('common:button:check') }}</el-button
|
||||||
|
>
|
||||||
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
|
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
|
||||||
({{ $t('trials:signature:label:mustBepdf') }})
|
({{ $t('trials:signature:label:mustBepdf') }})
|
||||||
</span>
|
</span>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:form:NeedConfirmedUserTypeIdList')"
|
<el-form-item
|
||||||
prop="NeedConfirmedUserTypeIdList">
|
:label="$t('dictionary:signature:form:NeedConfirmedUserTypeIdList')"
|
||||||
<el-select v-model="form.NeedConfirmedUserTypeIdList" style="width: 100%" multiple>
|
prop="NeedConfirmedUserTypeIdList"
|
||||||
<el-option v-for="item of userTypeOptions" :key="item.Id" :label="item.UserTypeShortName" :value="item.Id" />
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="form.NeedConfirmedUserTypeIdList"
|
||||||
|
style="width: 100%"
|
||||||
|
multiple
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of userTypeOptions"
|
||||||
|
:key="item.Id"
|
||||||
|
:label="item.UserTypeShortName"
|
||||||
|
:value="item.Id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:form:DocUserSignType')" prop="DocUserSignType">
|
<el-form-item
|
||||||
<el-switch v-model="form.DocUserSignType" :active-value="1" :inactive-value="0">
|
:label="$t('dictionary:signature:form:DocUserSignType')"
|
||||||
|
prop="DocUserSignType"
|
||||||
|
>
|
||||||
|
<el-switch
|
||||||
|
v-model="form.DocUserSignType"
|
||||||
|
:active-value="1"
|
||||||
|
:inactive-value="0"
|
||||||
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:form:SignViewMinimumMinutes')" prop="SignViewMinimumMinutes">
|
<el-form-item
|
||||||
<el-input-number v-model="form.SignViewMinimumMinutes" controls-position="right" :min="1" :max="50" />
|
:label="$t('dictionary:signature:form:SignViewMinimumMinutes')"
|
||||||
</el-form-item>
|
prop="SignViewMinimumMinutes"
|
||||||
<el-form-item :label="$t('dictionary:signature:form:CurrentStaffTrainDays')" prop="CurrentStaffTrainDays">
|
>
|
||||||
<el-input-number v-model="form.CurrentStaffTrainDays" controls-position="right" :min="0" :max="1000" />
|
<el-input-number
|
||||||
</el-form-item>
|
v-model="form.SignViewMinimumMinutes"
|
||||||
<el-form-item :label="$t('dictionary:signature:form:NewStaffTrainDays')" prop="NewStaffTrainDays">
|
controls-position="right"
|
||||||
<el-input-number v-model="form.NewStaffTrainDays" controls-position="right" :min="0" :max="1000" />
|
:min="1"
|
||||||
|
:max="50"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- <el-form-item v-if="form.Id !== ''" label="是否废除: ">
|
<!-- <el-form-item v-if="form.Id !== ''" label="是否废除: ">
|
||||||
<el-radio-group v-model="form.IsDeleted">
|
<el-radio-group v-model="form.IsDeleted">
|
||||||
|
|
@ -50,8 +105,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
||||||
<el-form-item style="text-align: right">
|
<el-form-item style="text-align: right">
|
||||||
<el-button size="small" type="primary" :disabled="form.FileTypeId === '' || form.Name === ''"
|
<el-button
|
||||||
:loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="form.FileTypeId === '' || form.Name === ''"
|
||||||
|
:loading="saveBtnLoading"
|
||||||
|
@click="handleSave"
|
||||||
|
>{{ $t('common:button:save') }}</el-button
|
||||||
|
>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
@ -77,12 +138,9 @@ export default {
|
||||||
FileTypeId: '',
|
FileTypeId: '',
|
||||||
Name: '',
|
Name: '',
|
||||||
Path: '',
|
Path: '',
|
||||||
IsPublish: false,
|
IsDeleted: false,
|
||||||
IsDeleted: true,
|
|
||||||
SignViewMinimumMinutes: null,
|
SignViewMinimumMinutes: null,
|
||||||
DocUserSignType: 0,
|
DocUserSignType: 0,
|
||||||
CurrentStaffTrainDays: 1,
|
|
||||||
NewStaffTrainDays: 14,
|
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
FileTypeId: [
|
FileTypeId: [
|
||||||
|
|
@ -138,11 +196,8 @@ export default {
|
||||||
this.form.Name = this.data.Name
|
this.form.Name = this.data.Name
|
||||||
this.form.Path = this.data.Path
|
this.form.Path = this.data.Path
|
||||||
this.form.IsDeleted = this.data.IsDeleted
|
this.form.IsDeleted = this.data.IsDeleted
|
||||||
this.form.IsPublish = this.data.IsPublish
|
|
||||||
this.form.SignViewMinimumMinutes = this.data.SignViewMinimumMinutes
|
this.form.SignViewMinimumMinutes = this.data.SignViewMinimumMinutes
|
||||||
this.form.DocUserSignType = this.data.DocUserSignType
|
this.form.DocUserSignType = this.data.DocUserSignType
|
||||||
this.form.CurrentStaffTrainDays = this.data.CurrentStaffTrainDays
|
|
||||||
this.form.NewStaffTrainDays = this.data.NewStaffTrainDays
|
|
||||||
}
|
}
|
||||||
this.loading = false
|
this.loading = false
|
||||||
},
|
},
|
||||||
|
|
@ -152,7 +207,7 @@ export default {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.dictionaryList = { ...res.Result }
|
this.dictionaryList = { ...res.Result }
|
||||||
})
|
})
|
||||||
.catch(() => { })
|
.catch(() => {})
|
||||||
},
|
},
|
||||||
// 获取用户类型下拉数据
|
// 获取用户类型下拉数据
|
||||||
getUserType() {
|
getUserType() {
|
||||||
|
|
@ -250,16 +305,13 @@ export default {
|
||||||
width: 80px;
|
width: 80px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-container .el-input--small {
|
.upload-container .el-input--small {
|
||||||
margin-bottom: 5px;
|
margin-bottom: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-container .el-icon-circle-check {
|
.upload-container .el-icon-circle-check {
|
||||||
color: #428bca;
|
color: #428bca;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.account_item_clear {
|
.account_item_clear {
|
||||||
.el-tag__close {
|
.el-tag__close {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
|
|
|
||||||
|
|
@ -1,223 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-form ref="attachmentFrom" v-loading="loading" :model="form" label-width="190px" size="small" :rules="rules"
|
|
||||||
class="upload-temporary-file">
|
|
||||||
<div class="base-dialog-body">
|
|
||||||
<el-form-item :label="$t('dictionary:signature:form:FileName')" prop="Name">
|
|
||||||
<el-input v-model="form.Name" clearable></el-input>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('dictionary:signature:form:OffLine')" prop="OffLine">
|
|
||||||
<el-switch v-model="form.OffLine" :active-value="true" :inactive-value="false"
|
|
||||||
:active-text="$fd('YesOrNo', true)" :inactive-text="$fd('YesOrNo', false)">
|
|
||||||
</el-switch>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('dictionary:signature:form:File')">
|
|
||||||
<div class="upload-container">
|
|
||||||
<el-upload class="upload-demo" action :accept="this.accept.join(',')" :before-upload="beforeUpload"
|
|
||||||
: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>
|
|
||||||
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
|
|
||||||
({{ $t('trials:signature:label:type').replace("xxx", this.accept.join(", ")) }})
|
|
||||||
</span>
|
|
||||||
</el-upload>
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
|
||||||
<el-form-item style="text-align: right">
|
|
||||||
<el-button size="small" type="primary" :disabled="form.FileTypeId === '' || form.Name === ''"
|
|
||||||
:loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import { addOrUpdateSystemDocumentAttachment } from '@/api/dictionary'
|
|
||||||
export default {
|
|
||||||
props: {
|
|
||||||
data: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
SystemDocumentId: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
form: {
|
|
||||||
Id: '',
|
|
||||||
Name: null,
|
|
||||||
FileFormat: null,
|
|
||||||
FileName: null,
|
|
||||||
FilePath: null,
|
|
||||||
FileSize: null,
|
|
||||||
OffLine: false,
|
|
||||||
SystemDocumentId: null,
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
Name: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: this.$t('common:ruleMessage:specify'),
|
|
||||||
trigger: ['change'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
fileList: [],
|
|
||||||
btnLoading: false,
|
|
||||||
saveBtnLoading: false,
|
|
||||||
loading: false,
|
|
||||||
accept: ['.jpg',
|
|
||||||
'.jpeg',
|
|
||||||
'.png',
|
|
||||||
'.pdf',
|
|
||||||
'.ppt',
|
|
||||||
'.pptx',
|
|
||||||
'.doc',
|
|
||||||
'.docx',
|
|
||||||
'.xls',
|
|
||||||
'.xlsx']
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.initForm()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async initForm() {
|
|
||||||
this.loading = true
|
|
||||||
if (this.data && this.data.Id) {
|
|
||||||
Object.keys(this.form).forEach(key => {
|
|
||||||
this.form[key] = this.data[key]
|
|
||||||
})
|
|
||||||
this.fileList = [
|
|
||||||
{
|
|
||||||
name: this.data.FileName,
|
|
||||||
url: this.data.FilePath,
|
|
||||||
path: this.data.FilePath,
|
|
||||||
},
|
|
||||||
]
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
},
|
|
||||||
beforeUpload(file) {
|
|
||||||
// 检测文件类型是否符合要求
|
|
||||||
if (this.checkFileSuffix(file.name)) {
|
|
||||||
this.fileList = []
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
this.$alert(this.$t('trials:signature:label:type').replace("xxx", this.accept.join(", ")))
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async handleUploadFile(param) {
|
|
||||||
this.loading = true
|
|
||||||
var file = await this.fileToBlob(param.file)
|
|
||||||
const res = await this.OSSclient.put(
|
|
||||||
`/System/DocumentToSign/${param.file.name}${new Date().getTime()}`,
|
|
||||||
file
|
|
||||||
)
|
|
||||||
this.fileList.push({
|
|
||||||
name: param.file.name,
|
|
||||||
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
|
|
||||||
this.form.FileFormat = param.file.name
|
|
||||||
.substring(param.file.name.lastIndexOf('.'))
|
|
||||||
.toLocaleLowerCase().split('.')[1]
|
|
||||||
this.loading = false
|
|
||||||
},
|
|
||||||
handleSave() {
|
|
||||||
this.$refs.attachmentFrom.validate((valid) => {
|
|
||||||
if (!valid) return false
|
|
||||||
if (!this.form.FilePath)
|
|
||||||
return this.$alert(this.$t('trials:signature:message:selectFile'))
|
|
||||||
this.saveBtnLoading = true
|
|
||||||
if (this.SystemDocumentId) this.form.SystemDocumentId = this.SystemDocumentId
|
|
||||||
addOrUpdateSystemDocumentAttachment(this.form)
|
|
||||||
.then((res) => {
|
|
||||||
this.saveBtnLoading = false
|
|
||||||
this.$emit('closeDialog')
|
|
||||||
this.$emit('getList')
|
|
||||||
this.$message.success(this.$t('common:message:updatedSuccessfully'))
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.saveBtnLoading = false
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
handleRemoveFile() {
|
|
||||||
this.fileList = []
|
|
||||||
this.form.FilePath = ''
|
|
||||||
this.form.FileSize = ''
|
|
||||||
this.form.FileFormat = ''
|
|
||||||
this.form.FileName = ''
|
|
||||||
},
|
|
||||||
handlePreview(file) {
|
|
||||||
if (file.fullPath) {
|
|
||||||
window.open(file.fullPath, '_blank')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleExceed(files, fileList) {
|
|
||||||
this.$message.warning(this.$t('upload:rule:maxFile1'))
|
|
||||||
},
|
|
||||||
checkFileSuffix(fileName) {
|
|
||||||
var typeArr = [
|
|
||||||
'jpg',
|
|
||||||
'jpeg',
|
|
||||||
'png',
|
|
||||||
'pdf',
|
|
||||||
'ppt',
|
|
||||||
'pptx',
|
|
||||||
'doc',
|
|
||||||
'docx',
|
|
||||||
'xls',
|
|
||||||
'xlsx',
|
|
||||||
]
|
|
||||||
var extendName = fileName
|
|
||||||
.substring(fileName.lastIndexOf('.') + 1)
|
|
||||||
.toLocaleLowerCase()
|
|
||||||
if (typeArr.indexOf(extendName) !== -1) {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss">
|
|
||||||
.upload-temporary-file {
|
|
||||||
.upload-container .el-upload--text {
|
|
||||||
border: none;
|
|
||||||
width: 80px;
|
|
||||||
height: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-container .el-input--small {
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.upload-container .el-icon-circle-check {
|
|
||||||
color: #428bca;
|
|
||||||
font-size: 13px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.account_item_clear {
|
|
||||||
.el-tag__close {
|
|
||||||
display: none !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,258 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-if="config.visible">
|
|
||||||
<base-model :config="config">
|
|
||||||
<template slot="dialog-body">
|
|
||||||
<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">
|
|
||||||
<el-table-column type="index" width="60" />
|
|
||||||
<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" 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)"
|
|
||||||
:inactive-text="$fd('YesOrNo', false)">
|
|
||||||
</el-switch>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
<el-table-column prop="CreateTime" :label="$t('dictionary:signature:attachmentList:CreateTime')"
|
|
||||||
sortable="custom" />
|
|
||||||
<el-table-column :label="$t('common:action:action')" min-width="120px">
|
|
||||||
<template slot-scope="scope">
|
|
||||||
<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)" v-if="!isView">
|
|
||||||
{{ $t('common:button:edit') }}
|
|
||||||
</el-button>
|
|
||||||
<!-- <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)" v-if="!isView">
|
|
||||||
{{ $t('common:button:delete') }}
|
|
||||||
</el-button>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
<!-- 新增/编辑附件 -->
|
|
||||||
<el-dialog :visible.sync="visible" :close-on-click-modal="false" :append-to-body="true" :title="title"
|
|
||||||
width="800px" custom-class="base-dialog-wrapper">
|
|
||||||
<attachmentForm v-if="visible" :data="rowData" :SystemDocumentId="SystemDocumentId"
|
|
||||||
@closeDialog="closeDialog" @getList="getAllList" />
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
</base-model>
|
|
||||||
<viewer ref="picture_perview2" style="margin: 0 10px"
|
|
||||||
v-if="rowData.FileFormat && ['png', 'jpg', 'jpeg'].includes(rowData.FileFormat.toLowerCase())"
|
|
||||||
:images="[`${OSSclientConfig.basePath}${rowData.FilePath}`]" :options="viewerOptions">
|
|
||||||
|
|
||||||
<img v-show="false" :src="`${OSSclientConfig.basePath}${rowData.FilePath}`" alt="Image" />
|
|
||||||
</viewer>
|
|
||||||
<!-- <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 { 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
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
config: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return {
|
|
||||||
visible: false,
|
|
||||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
|
||||||
width: '800px',
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isView: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
rowData: {
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
SystemDocumentId: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
searchData: defaultSearchData(),
|
|
||||||
visible: false,
|
|
||||||
title: null,
|
|
||||||
list: [],
|
|
||||||
rowData: {},
|
|
||||||
loading: false,
|
|
||||||
viewerOptions: {
|
|
||||||
toolbar: {
|
|
||||||
zoomIn: true,
|
|
||||||
zoomOut: true,
|
|
||||||
reset: true,
|
|
||||||
prev: false,
|
|
||||||
next: false,
|
|
||||||
rotateLeft: true,
|
|
||||||
rotateRight: true,
|
|
||||||
flipHorizontal: true,
|
|
||||||
flipVertical: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// perview_visible: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
SystemDocumentId: {
|
|
||||||
handler() {
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
immediate: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
closeDialog() {
|
|
||||||
this.visible = false
|
|
||||||
},
|
|
||||||
getAllList() {
|
|
||||||
this.getList()
|
|
||||||
this.$emit("getList")
|
|
||||||
},
|
|
||||||
async del(row) {
|
|
||||||
try {
|
|
||||||
let confirm = await this.$confirm(this.$t("dictionary:signature:attachmentList:message:del"))
|
|
||||||
if (!confirm) return false
|
|
||||||
this.loading = true
|
|
||||||
let res = await deleteSystemDocumentAttachment(row.Id)
|
|
||||||
this.loading = false
|
|
||||||
if (res.IsSuccess) {
|
|
||||||
this.getAllList()
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
console.log(err)
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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
|
|
||||||
},
|
|
||||||
async getList() {
|
|
||||||
try {
|
|
||||||
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
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this.loading = false
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async OffLine(row, val) {
|
|
||||||
try {
|
|
||||||
let data = Object.assign({}, row)
|
|
||||||
data.OffLine = val
|
|
||||||
this.loading = true
|
|
||||||
let res = await addOrUpdateSystemDocumentAttachment(data)
|
|
||||||
this.loading = false
|
|
||||||
if (res.IsSuccess) {
|
|
||||||
this.$t('dictionary:signature:attachmentList:updateSuccessfully')
|
|
||||||
this.getList()
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this.loading = false
|
|
||||||
row.OffLine = !row.OffLine
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
preview(data) {
|
|
||||||
// return this.perview_visible = true
|
|
||||||
this.rowData = Object.assign({}, data)
|
|
||||||
if (['.ppt',
|
|
||||||
'.pptx',
|
|
||||||
'.doc',
|
|
||||||
'.docx',
|
|
||||||
'.xls',
|
|
||||||
'.xlsx'].includes(`.${data.FileFormat.toLowerCase()}`)) {
|
|
||||||
this.$onlyOffice({
|
|
||||||
path: data.FilePath,
|
|
||||||
type: data.FileFormat,
|
|
||||||
title: data.Name
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (['.jpg',
|
|
||||||
'.jpeg',
|
|
||||||
'.png'].includes(`.${data.FileFormat.toLowerCase()}`)) {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.$refs['picture_perview2'].$viewer.show()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (['.pdf'].includes(`.${data.FileFormat.toLowerCase()}`)) {
|
|
||||||
this.$preview({
|
|
||||||
path: data.Path || data.FilePath,
|
|
||||||
type: 'pdf',
|
|
||||||
title: data.Name,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 排序
|
|
||||||
handleSortByColumn(column) {
|
|
||||||
if (column.order === 'ascending') {
|
|
||||||
this.searchData.Asc = true
|
|
||||||
} else {
|
|
||||||
this.searchData.Asc = false
|
|
||||||
}
|
|
||||||
this.searchData.SortField = column.prop
|
|
||||||
this.searchData.PageIndex = 1
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.name {
|
|
||||||
display: block;
|
|
||||||
width: 90%;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,312 +0,0 @@
|
||||||
<template>
|
|
||||||
<el-dialog :visible.sync="visible" :title="title" :fullscreen="true" append-to-body
|
|
||||||
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">
|
|
||||||
{{ $t('dictionary:signature:fileList') }}
|
|
||||||
</div>
|
|
||||||
<div class="left-content">
|
|
||||||
<!-- 检查层级 -->
|
|
||||||
<div id="imgList" style="height: 100%; overflow: hidden">
|
|
||||||
<template v-for="(item, index) in list">
|
|
||||||
<div :id="`img${item.Id}`" :key="item.Id" :class="{
|
|
||||||
'is-boxActive': item.Id === rowData.Id,
|
|
||||||
}" class="img-box" @click="selected(item)">
|
|
||||||
<div class="file-image">
|
|
||||||
<el-image v-if="
|
|
||||||
[
|
|
||||||
'jpeg',
|
|
||||||
'jpg',
|
|
||||||
'png',
|
|
||||||
].includes(item.FileFormat)
|
|
||||||
" 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 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}` }}
|
|
||||||
</div>
|
|
||||||
<el-tooltip v-else :content="item.Name" placement="bottom">
|
|
||||||
<div class="img-text">
|
|
||||||
{{ `${index + 1}. ${item.Name}` }}
|
|
||||||
</div>
|
|
||||||
</el-tooltip>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<!-- 预览图像 -->
|
|
||||||
<el-card class="box-card right">
|
|
||||||
<div style="width: 100%; height: 100%" v-if="[
|
|
||||||
'jpeg',
|
|
||||||
'jpg',
|
|
||||||
'png',
|
|
||||||
].includes(rowData.FileFormat)">
|
|
||||||
<imageViewer :rowData="rowData" />
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
|
|
||||||
<!-- <el-card class="box-card" style="width:300px;height:100%;padding: 10px;margin-left:10px;">
|
|
||||||
<CheckForm />
|
|
||||||
</el-card> -->
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
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'
|
|
||||||
const defaultSearchData = () => {
|
|
||||||
return {
|
|
||||||
PageIndex: 1,
|
|
||||||
PageSize: 1000,
|
|
||||||
Asc: false,
|
|
||||||
OffLine: null,
|
|
||||||
SortField: null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
export default {
|
|
||||||
name: 'Notice',
|
|
||||||
components: {
|
|
||||||
PreviewFile,
|
|
||||||
imageViewer
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
SystemDocumentId: {
|
|
||||||
type: String,
|
|
||||||
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: this.$t('dictionary:signature:fileList')
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
SystemDocumentId: {
|
|
||||||
handler() {
|
|
||||||
this.getList()
|
|
||||||
},
|
|
||||||
immediate: true,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
getsrc(type) {
|
|
||||||
return this[type.toLowerCase()]
|
|
||||||
},
|
|
||||||
selected(row) {
|
|
||||||
this.rowData = row
|
|
||||||
},
|
|
||||||
handleClose() {
|
|
||||||
this.$emit("update:visible", false)
|
|
||||||
},
|
|
||||||
async getList() {
|
|
||||||
try {
|
|
||||||
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] || {}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this.loading = false
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.img-container {
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
padding: 10px;
|
|
||||||
display: flex;
|
|
||||||
|
|
||||||
::-webkit-scrollbar {
|
|
||||||
width: 7px;
|
|
||||||
height: 7px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::-webkit-scrollbar-thumb {
|
|
||||||
border-radius: 10px;
|
|
||||||
background: #d0d0d0;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-card__body {
|
|
||||||
padding: 0px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.study-desc {
|
|
||||||
padding: 10px 5px;
|
|
||||||
line-height: 20px;
|
|
||||||
background-color: #d5d5d5;
|
|
||||||
font-weight: 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left {
|
|
||||||
width: 220px;
|
|
||||||
height: 100%;
|
|
||||||
|
|
||||||
::v-deep .el-card__body {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
|
|
||||||
.title {
|
|
||||||
height: 40px;
|
|
||||||
line-height: 40px;
|
|
||||||
border: 1ppx solid;
|
|
||||||
border: 1px solid #ebe7e7;
|
|
||||||
padding-left: 10px;
|
|
||||||
background-color: #4e4e4e;
|
|
||||||
color: #ffffff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.left-content {
|
|
||||||
flex: 1;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ::v-deep .el-tabs{
|
|
||||||
// height: 100%;
|
|
||||||
// }
|
|
||||||
// ::v-deep .el-tabs__header{
|
|
||||||
// height: 40px;
|
|
||||||
// }
|
|
||||||
// ::v-deep .el-tabs__content{
|
|
||||||
// flex: 1;
|
|
||||||
// overflow-y: auto;
|
|
||||||
// padding: 0;
|
|
||||||
// }
|
|
||||||
.img-box {
|
|
||||||
// position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
box-sizing: border-box;
|
|
||||||
border-bottom: 2px solid #f3f3f3;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
justify-content: flex-start;
|
|
||||||
padding: 5px 10px;
|
|
||||||
|
|
||||||
cursor: pointer;
|
|
||||||
// margin-bottom: 5px;
|
|
||||||
padding-left: 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-text {
|
|
||||||
display: inline-block;
|
|
||||||
width: calc(100% - 60px);
|
|
||||||
margin-left: 5px;
|
|
||||||
height: 50px;
|
|
||||||
line-height: 50px;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
/* 用省略号表示溢出的文本 */
|
|
||||||
white-space: nowrap;
|
|
||||||
}
|
|
||||||
|
|
||||||
.img-box:nth-last-child(1) {
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-boxActive {
|
|
||||||
// border-color: #409eff;
|
|
||||||
color: #409eff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.is-boxActiv:after {
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.right {
|
|
||||||
flex: 1;
|
|
||||||
height: 100%;
|
|
||||||
margin-left: 10px;
|
|
||||||
|
|
||||||
::v-deep .el-card__body {
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.switchBox {
|
|
||||||
width: 100%;
|
|
||||||
margin: 5px 0;
|
|
||||||
color: #4e4e4e;
|
|
||||||
|
|
||||||
.item {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
margin-bottom: 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.file-image {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-collapse-item__header {
|
|
||||||
background-color: #d5d5d5;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-collapse-item__header {
|
|
||||||
min-height: 48px;
|
|
||||||
height: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
::v-deep .el-collapse-item__content {
|
|
||||||
padding-bottom: 0;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,381 +0,0 @@
|
||||||
/* eslint-disable no-unused-vars */
|
|
||||||
<template>
|
|
||||||
<div style="width: 100%; height: 100%">
|
|
||||||
<transition name="viewer-fade">
|
|
||||||
<div ref="image-viewer__wrapper" tabindex="-1" class="image-viewer__wrapper" :style="{ 'z-index': 5 }">
|
|
||||||
<!-- Arrow -->
|
|
||||||
<!-- 工具栏 -->
|
|
||||||
<div class="image-viewer__btn image-viewer__actions">
|
|
||||||
<div class="image-viewer__actions__inner">
|
|
||||||
<i class="el-icon-zoom-out" @click="handleActions('zoomOut')" />
|
|
||||||
<i class="el-icon-zoom-in" @click="handleActions('zoomIn')" />
|
|
||||||
<i class="el-image-viewer__actions__divider" />
|
|
||||||
<i class="el-icon-c-scale-to-original" @click="toggleMode" />
|
|
||||||
<i class="el-image-viewer__actions__divider" />
|
|
||||||
<i class="el-icon-refresh-left" @click="handleActions('anticlocelise')" />
|
|
||||||
<i class="el-icon-refresh-right" @click="handleActions('clocelise')" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<!-- 图片 -->
|
|
||||||
<div id="image-viewer__canvas" class="image-viewer__canvas">
|
|
||||||
<img crossorigin="anonymous" :src="`${OSSclientConfig.basePath}${rowData.FilePath}`
|
|
||||||
" :style="imgStyle" style="max-width: 100%; max-height: 100%" @load="handleImgLoad" @error="handleImgError"
|
|
||||||
@mousedown="handleMouseDown" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</transition>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import { on, off } from 'element-ui/src/utils/dom'
|
|
||||||
import { rafThrottle, isFirefox } from 'element-ui/src/utils/util'
|
|
||||||
|
|
||||||
const mousewheelEventName = isFirefox() ? 'DOMMouseScroll' : 'mousewheel'
|
|
||||||
|
|
||||||
export default {
|
|
||||||
name: 'ImageViewer',
|
|
||||||
props: {
|
|
||||||
onSwitch: {
|
|
||||||
type: Function,
|
|
||||||
default: () => { },
|
|
||||||
},
|
|
||||||
onClose: {
|
|
||||||
type: Function,
|
|
||||||
default: () => { },
|
|
||||||
},
|
|
||||||
rowData:{
|
|
||||||
type: Object,
|
|
||||||
default: () => {
|
|
||||||
return {}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
transform: {
|
|
||||||
scale: 1,
|
|
||||||
deg: 0,
|
|
||||||
offsetX: 0,
|
|
||||||
offsetY: 0,
|
|
||||||
enableTransition: false,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
imgStyle() {
|
|
||||||
const { scale, deg, offsetX, offsetY, enableTransition } = this.transform
|
|
||||||
const style = {
|
|
||||||
transform: `scale(${scale}) rotate(${deg}deg)`,
|
|
||||||
transition: enableTransition ? 'transform .3s' : '',
|
|
||||||
'margin-left': `${offsetX}px`,
|
|
||||||
'margin-top': `${offsetY}px`,
|
|
||||||
}
|
|
||||||
return style
|
|
||||||
},
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
document.getElementById('image-viewer__canvas').onmousewheel = (event) => {
|
|
||||||
if (event.deltaY > 0) {
|
|
||||||
// 缩小
|
|
||||||
this.handleActions('zoomOut', {
|
|
||||||
zoomRate: 0.015,
|
|
||||||
enableTransition: false,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
// 放大
|
|
||||||
this.handleActions('zoomIn', {
|
|
||||||
zoomRate: 0.015,
|
|
||||||
enableTransition: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
this.deviceSupportInstall()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
hide() {
|
|
||||||
this.deviceSupportUninstall()
|
|
||||||
this.onClose()
|
|
||||||
},
|
|
||||||
deviceSupportInstall() {
|
|
||||||
this._keyDownHandler = (e) => {
|
|
||||||
e.stopPropagation()
|
|
||||||
const keyCode = e.keyCode
|
|
||||||
switch (keyCode) {
|
|
||||||
// ESC
|
|
||||||
case 27:
|
|
||||||
this.hide()
|
|
||||||
break
|
|
||||||
// SPACE
|
|
||||||
case 32:
|
|
||||||
this.toggleMode()
|
|
||||||
break
|
|
||||||
// LEFT_ARROW
|
|
||||||
case 37:
|
|
||||||
this.prev()
|
|
||||||
break
|
|
||||||
// UP_ARROW
|
|
||||||
case 38:
|
|
||||||
this.handleActions('zoomIn')
|
|
||||||
break
|
|
||||||
// RIGHT_ARROW
|
|
||||||
case 39:
|
|
||||||
this.next()
|
|
||||||
break
|
|
||||||
// DOWN_ARROW
|
|
||||||
case 40:
|
|
||||||
this.handleActions('zoomOut')
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this._mouseWheelHandler = rafThrottle((e) => {
|
|
||||||
const delta = e.wheelDelta ? e.wheelDelta : -e.detail
|
|
||||||
if (delta > 0) {
|
|
||||||
this.handleActions('zoomIn', {
|
|
||||||
zoomRate: 0.015,
|
|
||||||
enableTransition: false,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
this.handleActions('zoomOut', {
|
|
||||||
zoomRate: 0.015,
|
|
||||||
enableTransition: false,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
on(document, 'keydown', this._keyDownHandler)
|
|
||||||
|
|
||||||
on(document, mousewheelEventName, null)
|
|
||||||
// on(document, mousewheelEventName, this._mouseWheelHandler)
|
|
||||||
},
|
|
||||||
deviceSupportUninstall() {
|
|
||||||
off(document, 'keydown', this._keyDownHandler)
|
|
||||||
off(document, mousewheelEventName, this._mouseWheelHandler)
|
|
||||||
this._keyDownHandler = null
|
|
||||||
this._mouseWheelHandler = null
|
|
||||||
},
|
|
||||||
handleImgLoad(e) {
|
|
||||||
this.loading = false
|
|
||||||
},
|
|
||||||
handleImgError(e) {
|
|
||||||
this.loading = false
|
|
||||||
e.target.alt = '加载失败'
|
|
||||||
},
|
|
||||||
handleMouseDown(e) {
|
|
||||||
if (this.loading || e.button !== 0) return
|
|
||||||
|
|
||||||
const { offsetX, offsetY } = this.transform
|
|
||||||
const startX = e.pageX
|
|
||||||
const startY = e.pageY
|
|
||||||
this._dragHandler = rafThrottle((ev) => {
|
|
||||||
this.transform.offsetX = offsetX + ev.pageX - startX
|
|
||||||
this.transform.offsetY = offsetY + ev.pageY - startY
|
|
||||||
})
|
|
||||||
on(document, 'mousemove', this._dragHandler)
|
|
||||||
on(document, 'mouseup', (ev) => {
|
|
||||||
off(document, 'mousemove', this._dragHandler)
|
|
||||||
})
|
|
||||||
|
|
||||||
e.preventDefault()
|
|
||||||
},
|
|
||||||
reset() {
|
|
||||||
this.transform = {
|
|
||||||
scale: 1,
|
|
||||||
deg: 0,
|
|
||||||
offsetX: 0,
|
|
||||||
offsetY: 0,
|
|
||||||
enableTransition: false,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
toggleMode() {
|
|
||||||
if (this.loading) return
|
|
||||||
this.reset()
|
|
||||||
},
|
|
||||||
handleActions(action, options = {}) {
|
|
||||||
if (this.loading) return
|
|
||||||
const { zoomRate, rotateDeg, enableTransition } = {
|
|
||||||
zoomRate: 0.2,
|
|
||||||
rotateDeg: 90,
|
|
||||||
enableTransition: true,
|
|
||||||
...options,
|
|
||||||
}
|
|
||||||
const { transform } = this
|
|
||||||
switch (action) {
|
|
||||||
case 'zoomOut':
|
|
||||||
if (transform.scale > 0.2) {
|
|
||||||
transform.scale = parseFloat(
|
|
||||||
(transform.scale - zoomRate).toFixed(3)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'zoomIn':
|
|
||||||
if (transform.scale < 5) {
|
|
||||||
transform.scale = parseFloat(
|
|
||||||
(transform.scale + zoomRate).toFixed(3)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
case 'clocelise':
|
|
||||||
transform.deg += rotateDeg
|
|
||||||
break
|
|
||||||
case 'anticlocelise':
|
|
||||||
transform.deg -= rotateDeg
|
|
||||||
break
|
|
||||||
}
|
|
||||||
transform.enableTransition = enableTransition
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.image-viewer__wrapper {
|
|
||||||
position: relative;
|
|
||||||
top: 0;
|
|
||||||
right: 0;
|
|
||||||
bottom: 0;
|
|
||||||
left: 0;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__btn {
|
|
||||||
position: absolute;
|
|
||||||
z-index: 1;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
border-radius: 50%;
|
|
||||||
opacity: 0.8;
|
|
||||||
cursor: pointer;
|
|
||||||
box-sizing: border-box;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__close {
|
|
||||||
display: none;
|
|
||||||
top: 40px;
|
|
||||||
right: 40px;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
font-size: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer_desc {
|
|
||||||
position: absolute;
|
|
||||||
top: 40px;
|
|
||||||
left: 40px;
|
|
||||||
font-size: 15px;
|
|
||||||
padding: 5px;
|
|
||||||
height: 30px;
|
|
||||||
width: 70px;
|
|
||||||
line-height: 20px;
|
|
||||||
text-align: center;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #606266;
|
|
||||||
border-color: #fff;
|
|
||||||
z-index: 1;
|
|
||||||
border-radius: 17px;
|
|
||||||
// border-radius: 2%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__canvas {
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
transform: translateY(-50%);
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__actions {
|
|
||||||
left: 50%;
|
|
||||||
bottom: 30px;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
width: 282px;
|
|
||||||
height: 44px;
|
|
||||||
padding: 0 23px;
|
|
||||||
background-color: #606266;
|
|
||||||
border-color: #fff;
|
|
||||||
border-radius: 22px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__actions__inner {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
text-align: justify;
|
|
||||||
cursor: default;
|
|
||||||
font-size: 23px;
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: space-around;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__next,
|
|
||||||
.image-viewer__prev {
|
|
||||||
top: 50%;
|
|
||||||
width: 44px;
|
|
||||||
height: 44px;
|
|
||||||
font-size: 24px;
|
|
||||||
color: #fff;
|
|
||||||
background-color: #606266;
|
|
||||||
border-color: #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__prev {
|
|
||||||
transform: translateY(-50%);
|
|
||||||
left: 40px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__next {
|
|
||||||
transform: translateY(-50%);
|
|
||||||
right: 40px;
|
|
||||||
text-indent: 2px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.image-viewer__mask {
|
|
||||||
position: absolute;
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
opacity: 0.5;
|
|
||||||
// background:#000
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewer-fade-enter-active {
|
|
||||||
animation: viewer-fade-in 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.viewer-fade-leave-active {
|
|
||||||
animation: viewer-fade-out 0.3s;
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes viewer-fade-in {
|
|
||||||
0% {
|
|
||||||
transform: translate3d(0, -20px, 0);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: translate3d(0, 0, 0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes viewer-fade-out {
|
|
||||||
0% {
|
|
||||||
transform: translate3d(0, 0, 0);
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
transform: translate3d(0, -20px, 0);
|
|
||||||
opacity: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,103 +1,80 @@
|
||||||
<template>
|
<template>
|
||||||
<BaseContainer>
|
<BaseContainer>
|
||||||
<template slot="title-container">
|
|
||||||
<el-row v-if="isSystem" style="width: 100%;">
|
|
||||||
<el-col :span="12">
|
|
||||||
<h3>{{ TITLE }}</h3>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12" style="text-align:right;">
|
|
||||||
<h3>
|
|
||||||
<Pagination class="page" :total="total" :page.sync="searchData.pageIndex" :limit.sync="searchData.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>
|
|
||||||
</template>
|
|
||||||
<template slot="search-container">
|
<template slot="search-container">
|
||||||
<el-form :inline="true" size="small">
|
<el-form :inline="true" size="small">
|
||||||
<el-form-item :label="$t('dictionary:signature:search:FileTypeId')">
|
<el-form-item :label="$t('dictionary:signature:search:FileTypeId')">
|
||||||
<el-select v-model="searchData.FileTypeId" style="width: 150px" clearable>
|
<el-select v-model="searchData.FileTypeId" style="width: 150px">
|
||||||
<el-option v-for="item of $d.Sys_Document" :key="item.id" :label="item.label" :value="item.id" />
|
<el-option
|
||||||
|
v-for="item of dict.type.Sys_Document"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:search:Name')">
|
<el-form-item :label="$t('dictionary:signature:search:Name')">
|
||||||
<el-input v-model="searchData.Name" style="width: 130px" clearable />
|
<el-input v-model="searchData.Name" style="width: 130px" clearable />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:signature:table:NeedConfirmedUserTypes')">
|
|
||||||
<el-select v-model="searchData.UserTypeId" style="width: 150px" clearable>
|
|
||||||
<el-option v-for="item of userTypeOptions" :key="item.Id" :label="item.UserTypeShortName"
|
|
||||||
:value="item.Id" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('dictionary:signature:table:IsDeleted')">
|
|
||||||
<el-select v-model="searchData.IsDeleted" style="width: 150px" clearable>
|
|
||||||
<el-option v-for="item of $d.TrainingStatus" :key="item.id" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('dictionary:signature:table:DocUserSignType')">
|
|
||||||
<el-select v-model="searchData.DocUserSignType" style="width: 150px" clearable>
|
|
||||||
<el-option v-for="item of $d.ReadingYesOrNo" :key="item.id" :label="item.label" :value="item.value" />
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item :label="$t('dictionary:signature:table:createTime')">
|
|
||||||
<el-date-picker v-model="timeList" @change="changeTimeList" value-format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
:default-time="['00:00:00', '23:59:59']" type="datetimerange">
|
|
||||||
</el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<!-- 查询 -->
|
<!-- 查询 -->
|
||||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 重置 -->
|
<!-- 重置 -->
|
||||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="handleReset"
|
||||||
|
>
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<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-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
style="margin-left: auto; margin-bottom: 10px"
|
||||||
|
size="small"
|
||||||
|
@click="handleAdd"
|
||||||
|
>
|
||||||
|
{{ $t('common:button:new') }}
|
||||||
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
<template slot="main-container">
|
<template slot="main-container">
|
||||||
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="loading" :data="list" stripe height="100"
|
<el-table
|
||||||
@sort-change="handleSortByColumn" @selection-change="handleSelectionChange">
|
v-adaptive="{ bottomOffset: 60 }"
|
||||||
<!-- <el-table-column type="index" width="40" /> -->
|
v-loading="loading"
|
||||||
<el-table-column type="selection" width="55" :selectable="handleSelectable">
|
:data="list"
|
||||||
</el-table-column>
|
stripe
|
||||||
<el-table-column prop="FileType" :label="$t('dictionary:signature:table:FileType')" show-overflow-tooltip
|
height="100"
|
||||||
sortable="custom" min-width="120px" />
|
@sort-change="handleSortByColumn"
|
||||||
<el-table-column prop="Name" :label="$t('dictionary:signature:table:Name')" show-overflow-tooltip
|
>
|
||||||
sortable="custom" min-width="120px" />
|
<el-table-column type="index" width="40" />
|
||||||
<el-table-column prop="AttachmentCount" :label="$t('dictionary:signature:table:AttachmentCount')"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" min-width="150px">
|
prop="FileType"
|
||||||
<template slot-scope="scope">
|
:label="$t('dictionary:signature:table:FileType')"
|
||||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">
|
show-overflow-tooltip
|
||||||
{{ scope.row.AttachmentCount }}
|
sortable="custom"
|
||||||
<i class="el-icon-upload2" />
|
/>
|
||||||
</el-button>
|
<el-table-column
|
||||||
</template>
|
prop="Name"
|
||||||
</el-table-column>
|
:label="$t('dictionary:signature:table:Name')"
|
||||||
<el-table-column prop="SignViewMinimumMinutes" :label="$t('dictionary:signature:table:SignViewMinimumMinutes')"
|
show-overflow-tooltip
|
||||||
show-overflow-tooltip sortable="custom" min-width="200px" />
|
sortable="custom"
|
||||||
<el-table-column prop="CurrentStaffTrainDays" :label="$t('dictionary:signature:table:CurrentStaffTrainDays')"
|
/>
|
||||||
show-overflow-tooltip sortable="custom" min-width="200px" />
|
|
||||||
<el-table-column prop="NewStaffTrainDays" :label="$t('dictionary:signature:table:NewStaffTrainDays')"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" min-width="200px" />
|
prop="SignViewMinimumMinutes"
|
||||||
<el-table-column prop="NeedConfirmedUserTypes" :label="$t('dictionary:signature:table:NeedConfirmedUserTypes')"
|
:label="$t('dictionary:signature:table:SignViewMinimumMinutes')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="110"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="NeedConfirmedUserTypes"
|
||||||
|
:label="$t('dictionary:signature:table:NeedConfirmedUserTypes')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{
|
{{
|
||||||
scope.row.NeedConfirmedUserTypes
|
scope.row.NeedConfirmedUserTypes
|
||||||
|
|
@ -106,8 +83,12 @@
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="IsDeleted" :label="$t('dictionary:signature:table:IsDeleted')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="120px">
|
prop="IsDeleted"
|
||||||
|
:label="$t('dictionary:signature:table:IsDeleted')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
|
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
|
||||||
$fd('TrainingStatus', scope.row.IsDeleted)
|
$fd('TrainingStatus', scope.row.IsDeleted)
|
||||||
|
|
@ -117,89 +98,103 @@
|
||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="IsPublish" :label="$t('dictionary:signature:table:IsPublish')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="120px">
|
prop="DocUserSignType"
|
||||||
<template slot-scope="scope">
|
:label="$t('dictionary:signature:table:DocUserSignType')"
|
||||||
<el-tag :type="scope.row.IsPublish ? 'primary' : 'danger'">{{
|
show-overflow-tooltip
|
||||||
$fd('AttachmentPublishStatus', scope.row.IsPublish)
|
sortable="custom"
|
||||||
}}</el-tag>
|
min-width="90"
|
||||||
</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">
|
<template slot-scope="scope">
|
||||||
{{ $fd('ReadingYesOrNo', Number(scope.row.DocUserSignType)) }}
|
{{ $fd('ReadingYesOrNo', Number(scope.row.DocUserSignType)) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="CreateTime" :label="$t('dictionary:signature:table:CreateTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="180px" />
|
prop="CreateTime"
|
||||||
|
:label="$t('dictionary:signature:table:CreateTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-table-column :label="$t('common:action:action')" min-width="240px" fixed="right">
|
<el-table-column :label="$t('common:action:action')" min-width="120">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button circle icon="el-icon-view" @click="handlePreview(scope.row)"
|
<el-button type="text" @click="handlePreview(scope.row)">
|
||||||
:title="$t('common:button:preview')">
|
{{ $t('common:button:preview') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button circle icon="el-icon-edit-outline" :title="$t('common:button:edit')"
|
<el-button type="text" @click="handleEdit(scope.row)">
|
||||||
@click="handleEdit(scope.row)">
|
{{ $t('common:button:edit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :disabled="scope.row.IsPublish" circle icon="el-icon-position"
|
<el-button
|
||||||
:title="$t('dictionary:signature:button:publish')" @click="publishSystemDocument([scope.row])">
|
:disabled="scope.row.IsDeleted"
|
||||||
|
type="text"
|
||||||
|
@click="handleRepeal(scope.row)"
|
||||||
|
>
|
||||||
|
{{ $t('common:button:revoke') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button :disabled="scope.row.IsDeleted" circle icon="el-icon-close" :title="$t('common:button:revoke')"
|
<el-button type="text" @click="handleDelete(scope.row)">
|
||||||
@click="handleRepeal([scope.row])">
|
{{ $t('common:button:delete') }}
|
||||||
</el-button>
|
|
||||||
<el-button circle icon="el-icon-delete" :title="$t('common:button:delete')"
|
|
||||||
@click="handleDelete(scope.row)">
|
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<!-- 分页组件 -->
|
<!-- 分页组件 -->
|
||||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination
|
||||||
@pagination="getList" v-if="!isSystem" />
|
class="page"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="searchData.PageIndex"
|
||||||
|
:limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
|
||||||
<!-- 新增/编辑 -->
|
<!-- 新增/编辑 -->
|
||||||
<el-dialog v-if="editVisible" :visible.sync="editVisible" :close-on-click-modal="false" :title="title"
|
<el-dialog
|
||||||
width="600px" custom-class="base-dialog-wrapper">
|
v-if="editVisible"
|
||||||
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
|
:visible.sync="editVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:title="title"
|
||||||
|
width="600px"
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
|
<TemplateForm
|
||||||
|
:data="currentRow"
|
||||||
|
@closeDialog="closeDialog"
|
||||||
|
@getList="getList"
|
||||||
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!--附件列表-->
|
|
||||||
<attachmentList v-if="config.visible" :config="config" :rowData="currentRow" :SystemDocumentId="SystemDocumentId"
|
|
||||||
@getList="getList" />
|
|
||||||
<!-- 预览文件 -->
|
<!-- 预览文件 -->
|
||||||
<attachmentPreview :SystemDocumentId="SystemDocumentId" :visible.sync="perview_visible" :isView="true"
|
<el-dialog
|
||||||
v-if="perview_visible" />
|
v-if="previewVisible"
|
||||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="$t('common:button:preview')"
|
:visible.sync="previewVisible"
|
||||||
:fullscreen="true" append-to-body custom-class="base-dialog-wrapper">
|
:title="$t('common:button:preview')"
|
||||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
:fullscreen="true"
|
||||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
append-to-body
|
||||||
$t('trials:signRecords:table:AttachmentCount') }} ({{
|
custom-class="base-dialog-wrapper"
|
||||||
currentRow.AttachmentCount }})</span>
|
>
|
||||||
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
<div
|
||||||
<PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" />
|
class="base-modal-body"
|
||||||
|
style="border: 2px solid #ccc; padding: 10px"
|
||||||
|
>
|
||||||
|
<PreviewFile
|
||||||
|
v-if="previewVisible"
|
||||||
|
:file-path="currentPath"
|
||||||
|
:file-type="currentType"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</template>
|
</template>
|
||||||
</BaseContainer>
|
</BaseContainer>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getSystemDocumentList, deleteSystemDocument, publishSystemDocument, outLineSystemDocument, getSystemDocumentAttachmentList } from '@/api/dictionary'
|
import { getSystemDocumentList, deleteSystemDocument } from '@/api/dictionary'
|
||||||
import { userAbandonDoc, getTrialUserTypeList } from '@/api/trials'
|
import { userAbandonDoc } from '@/api/trials'
|
||||||
import BaseContainer from '@/components/BaseContainer'
|
import BaseContainer from '@/components/BaseContainer'
|
||||||
import Pagination from '@/components/Pagination'
|
import Pagination from '@/components/Pagination'
|
||||||
import TemplateForm from './TemplateForm'
|
import TemplateForm from './TemplateForm'
|
||||||
|
|
||||||
import attachmentList from './attachmentList'
|
|
||||||
import PreviewFile from '@/components/PreviewFile/index'
|
import PreviewFile from '@/components/PreviewFile/index'
|
||||||
import attachmentPreview from './attachmentPreview'
|
|
||||||
const searchDataDefault = () => {
|
const searchDataDefault = () => {
|
||||||
return {
|
return {
|
||||||
FileTypeId: '',
|
FileTypeId: '',
|
||||||
BeginCreateTime: null,
|
|
||||||
EndCreateTime: null,
|
|
||||||
IsDeleted: null,
|
|
||||||
DocUserSignType: null,
|
|
||||||
UserTypeId: null,
|
|
||||||
Name: '',
|
Name: '',
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
PageSize: 20,
|
PageSize: 20,
|
||||||
|
|
@ -207,18 +202,8 @@ const searchDataDefault = () => {
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
name: 'SignatureTemplate',
|
name: 'SignatureTemplate',
|
||||||
components: { BaseContainer, Pagination, TemplateForm, PreviewFile, attachmentList, attachmentPreview },
|
components: { BaseContainer, Pagination, TemplateForm, PreviewFile },
|
||||||
dicts: ['Sys_Document'],
|
dicts: ['Sys_Document'],
|
||||||
props: {
|
|
||||||
isSystem: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false
|
|
||||||
},
|
|
||||||
TITLE: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchData: searchDataDefault(),
|
searchData: searchDataDefault(),
|
||||||
|
|
@ -231,82 +216,12 @@ export default {
|
||||||
previewVisible: false,
|
previewVisible: false,
|
||||||
title: '',
|
title: '',
|
||||||
loading: false,
|
loading: false,
|
||||||
userTypeOptions: [],
|
|
||||||
timeList: [],
|
|
||||||
attachment_Visible: false,
|
|
||||||
SystemDocumentId: null,
|
|
||||||
config: {
|
|
||||||
visible: false,
|
|
||||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
|
||||||
width: '800px',
|
|
||||||
},
|
|
||||||
multipleSelection: [],
|
|
||||||
perview_visible: false
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.getList()
|
this.getList()
|
||||||
this.getUserType()
|
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
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.currentRow = { ...row }
|
|
||||||
if (!isList) {
|
|
||||||
this.perview_visible = true
|
|
||||||
} else {
|
|
||||||
this.config.visible = true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeTimeList() {
|
|
||||||
if (this.timeList) {
|
|
||||||
this.searchData.BeginCreateTime = this.timeList[0]
|
|
||||||
this.searchData.EndCreateTime = this.timeList[1]
|
|
||||||
} else {
|
|
||||||
this.searchData.BeginCreateTime = null
|
|
||||||
this.searchData.EndCreateTime = null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// 获取用户类型下拉数据
|
|
||||||
getUserType() {
|
|
||||||
getTrialUserTypeList()
|
|
||||||
.then((res) => {
|
|
||||||
this.userTypeOptions = res.Result
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
},
|
|
||||||
// 获取系统文件数据
|
// 获取系统文件数据
|
||||||
getList() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
@ -336,23 +251,12 @@ export default {
|
||||||
this.editVisible = true
|
this.editVisible = true
|
||||||
},
|
},
|
||||||
// 预览
|
// 预览
|
||||||
async handlePreview(row) {
|
handlePreview(row) {
|
||||||
const { Name, FullFilePath } = row
|
const { Name, FullFilePath } = row
|
||||||
this.currentPath = FullFilePath
|
this.currentPath = FullFilePath
|
||||||
this.currentType = row.Name
|
this.currentType = row.Name
|
||||||
? Name.substring(Name.lastIndexOf('.') + 1).toLocaleLowerCase()
|
? 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
|
this.previewVisible = true
|
||||||
},
|
},
|
||||||
// 编辑
|
// 编辑
|
||||||
|
|
@ -368,13 +272,8 @@ export default {
|
||||||
distinguishCancelAndClose: true,
|
distinguishCancelAndClose: true,
|
||||||
})
|
})
|
||||||
.then(() => {
|
.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
|
this.loading = true
|
||||||
outLineSystemDocument(data)
|
userAbandonDoc(row.Id, true)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
|
|
@ -388,7 +287,7 @@ export default {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.catch(() => { })
|
.catch(() => {})
|
||||||
},
|
},
|
||||||
// 删除
|
// 删除
|
||||||
handleDelete(row) {
|
handleDelete(row) {
|
||||||
|
|
@ -418,7 +317,6 @@ export default {
|
||||||
// 关闭弹窗
|
// 关闭弹窗
|
||||||
closeDialog() {
|
closeDialog() {
|
||||||
this.editVisible = false
|
this.editVisible = false
|
||||||
this.attachment_Visible = false
|
|
||||||
},
|
},
|
||||||
// 重置
|
// 重置
|
||||||
handleReset() {
|
handleReset() {
|
||||||
|
|
|
||||||
|
|
@ -4,160 +4,319 @@
|
||||||
<el-form :inline="true" class="base-search-form">
|
<el-form :inline="true" class="base-search-form">
|
||||||
<!-- 是否需要回执 -->
|
<!-- 是否需要回执 -->
|
||||||
<el-form-item :label="$t('trials:emailManageCfg:title:isReturnRequired')" v-if="!systemLevel">
|
<el-form-item :label="$t('trials:emailManageCfg:title:isReturnRequired')" v-if="!systemLevel">
|
||||||
<el-select v-model="searchData.IsReturnRequired" clearable style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
|
v-model="searchData.IsReturnRequired"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 是否加急 -->
|
<!-- 是否加急 -->
|
||||||
<el-form-item :label="$t('dictionary:email:label:IsUrgent')" v-if="!systemLevel">
|
<el-form-item :label="$t('dictionary:email:label:IsUrgent')" v-if="!systemLevel">
|
||||||
<el-select v-model="searchData.IsUrgent" clearable style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
|
v-model="searchData.IsUrgent"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 是否启用 -->
|
<!-- 是否启用 -->
|
||||||
<el-form-item :label="$t('trials:emailManageCfg:table:IsEnable')" v-if="!systemLevel">
|
<el-form-item :label="$t('trials:emailManageCfg:table:IsEnable')" v-if="!systemLevel">
|
||||||
<el-select v-model="searchData.IsEnable" clearable style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
|
v-model="searchData.IsEnable"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:auditRecord:table:criterion')" v-if="isDistinguishCriteria && !systemLevel">
|
<el-form-item
|
||||||
<el-select v-model="searchData.CriterionTypeEnum" clearable style="width: 100px">
|
:label="$t('trials:auditRecord:table:criterion')"
|
||||||
<el-option v-for="item of $d.CriterionType" :value="item.value" :label="item.label" :key="item.id" />
|
v-if="isDistinguishCriteria && !systemLevel"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.CriterionTypeEnum"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.CriterionType"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:emailManageCfg:form:BusinessModule')">
|
<el-form-item :label="$t('trials:emailManageCfg:form:BusinessModule')">
|
||||||
<el-select v-model="searchData.BusinessModuleEnum" clearable style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item of $d.BusinessModule" :value="item.value" :label="item.label" :key="item.id" />
|
v-model="searchData.BusinessModuleEnum"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.BusinessModule"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:emailManageCfg:form:BusinessScenario')">
|
<el-form-item
|
||||||
<el-select v-model="searchData.BusinessScenarioEnum" clearable style="width: 100px">
|
:label="$t('trials:emailManageCfg:form:BusinessScenario')"
|
||||||
<el-option v-for="item of $d.Email_BusinessScenario" :value="item.value" :label="item.label"
|
>
|
||||||
:key="item.id" />
|
<el-select
|
||||||
|
v-model="searchData.BusinessScenarioEnum"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.Email_BusinessScenario"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:emailManageCfg:form:ToUserType')">
|
<el-form-item :label="$t('trials:emailManageCfg:form:ToUserType')">
|
||||||
<el-select v-model="searchData.ToUserType" clearable style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item of UserTypeList" :value="item.value" :label="item.label" :key="item.id" />
|
v-model="searchData.ToUserType"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of UserTypeList"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:emailManageCfg:form:EmailUrgent')" v-if="systemLevel === 1">
|
<el-form-item
|
||||||
<el-select v-model="searchData.EmailUrgentEnum" clearable style="width: 100px">
|
:label="$t('trials:emailManageCfg:form:EmailUrgent')"
|
||||||
<el-option v-for="item of $d.EmailUrgent" :value="item.value" :label="item.label" :key="item.id" />
|
v-if="systemLevel === 1"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.EmailUrgentEnum"
|
||||||
|
clearable
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.EmailUrgent"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:key="item.id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="handleReset"
|
||||||
|
>
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
</el-form>
|
||||||
<el-button type="primary" @click="handleExport">
|
<span style="margin-left: auto">
|
||||||
{{ $t('common:button:export') }}
|
<el-button type="primary" @click="handleExport">
|
||||||
</el-button>
|
{{ $t('common:button:export') }}
|
||||||
<!-- <el-button
|
</el-button>
|
||||||
|
<!-- <el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="mini"
|
size="mini"
|
||||||
>
|
>
|
||||||
场景配置
|
场景配置
|
||||||
</el-button> -->
|
</el-button> -->
|
||||||
<el-button type="primary" @click="handleAdd">
|
<el-button type="primary" @click="handleAdd">
|
||||||
{{ $t('common:button:new') }}
|
{{ $t('common:button:new') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</span>
|
||||||
</el-form>
|
|
||||||
</div>
|
</div>
|
||||||
<!-- 受试者列表 -->
|
<!-- 受试者列表 -->
|
||||||
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" :data="list" stripe height="100" style="width: 100%"
|
<el-table
|
||||||
@sort-change="handleSortByColumn">
|
v-loading="loading"
|
||||||
|
v-adaptive="{ bottomOffset: 45 }"
|
||||||
|
:data="list"
|
||||||
|
stripe
|
||||||
|
height="100"
|
||||||
|
style="width: 100%"
|
||||||
|
@sort-change="handleSortByColumn"
|
||||||
|
>
|
||||||
<el-table-column type="index" width="40" />
|
<el-table-column type="index" width="40" />
|
||||||
<!-- Code -->
|
<!-- Code -->
|
||||||
<el-table-column prop="Code" :label="$t('trials:emailManageCfg:title:code')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="100" />
|
prop="Code"
|
||||||
<el-table-column v-if="isDistinguishCriteria" prop="TrialReadingCriterionId"
|
:label="$t('trials:emailManageCfg:title:code')"
|
||||||
:label="$t('trials:reviewTrack:table:criterionName')" show-overflow-tooltip sortable="custom" min-width="120">
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="100"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="isDistinguishCriteria"
|
||||||
|
prop="TrialReadingCriterionId"
|
||||||
|
:label="$t('trials:reviewTrack:table:criterionName')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="120"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('CriterionType', scope.row.CriterionTypeEnum) }}
|
{{ $fd('CriterionType', scope.row.CriterionTypeEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 邮件主题(中文) -->
|
<!-- 邮件主题(中文) -->
|
||||||
<el-table-column prop="EmailTopicCN" :label="$t('trials:emailManageCfg:table:EmailTopicCN')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="160" />
|
prop="EmailTopicCN"
|
||||||
|
:label="$t('trials:emailManageCfg:table:EmailTopicCN')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
<!-- 邮件主题(英文) -->
|
<!-- 邮件主题(英文) -->
|
||||||
<el-table-column prop="EmailTopic" :label="$t('trials:emailManageCfg:table:EmailTopic')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="160" />
|
prop="EmailTopic"
|
||||||
|
:label="$t('trials:emailManageCfg:table:EmailTopic')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
<!-- 业务层级 -->
|
<!-- 业务层级 -->
|
||||||
<el-table-column prop="BusinessLevelEnum" :label="$t('dictionary:email:label:businessLevel')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="150">
|
prop="BusinessLevelEnum"
|
||||||
|
:label="$t('dictionary:email:label:businessLevel')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="150"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('BusinessLevel', scope.row.BusinessLevelEnum) }}
|
{{ $fd('BusinessLevel', scope.row.BusinessLevelEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 业务模块 -->
|
<!-- 业务模块 -->
|
||||||
<el-table-column prop="BusinessModuleEnum" :label="$t('dictionary:email:label:businessModule')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="160">
|
prop="BusinessModuleEnum"
|
||||||
|
:label="$t('dictionary:email:label:businessModule')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="160"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('BusinessModule', scope.row.BusinessModuleEnum) }}
|
{{ $fd('BusinessModule', scope.row.BusinessModuleEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 业务场景 -->
|
<!-- 业务场景 -->
|
||||||
<el-table-column prop="BusinessScenarioEnum" :label="$t('trials:emailManageCfg:table:BusinessScenarioEnum')"
|
<el-table-column
|
||||||
sortable="custom" show-overflow-tooltip min-width="130">
|
prop="BusinessScenarioEnum"
|
||||||
|
:label="$t('trials:emailManageCfg:table:BusinessScenarioEnum')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="130"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('Email_BusinessScenario', scope.row.BusinessScenarioEnum) }}
|
{{ $fd('Email_BusinessScenario', scope.row.BusinessScenarioEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 收件人v-if="systemLevel !== 1" -->
|
<!-- 收件人v-if="systemLevel !== 1" -->
|
||||||
<el-table-column prop="ToUserTypeList" :label="$t('trials:emailManageCfg:title:toUserTypeList')"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="100">
|
prop="ToUserTypeList"
|
||||||
|
:label="$t('trials:emailManageCfg:title:toUserTypeList')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="100"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{
|
{{
|
||||||
scope.row.ToUserTypeList.length > 0
|
scope.row.ToUserTypeList.length > 0
|
||||||
? scope.row.ToUserTypeList.map((v) => $fd('UserType', v)).join(
|
? scope.row.ToUserTypeList.map((v) => $fd('UserType', v)).join(
|
||||||
'、'
|
'、'
|
||||||
)
|
)
|
||||||
: ''
|
: ''
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 抄送人v-if="!systemLevel" -->
|
<!-- 抄送人v-if="!systemLevel" -->
|
||||||
<el-table-column prop="CopyUserTypeList" :label="$t('trials:emailManageCfg:title:copyUserTypeList')"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="100">
|
prop="CopyUserTypeList"
|
||||||
|
:label="$t('trials:emailManageCfg:title:copyUserTypeList')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="100"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{
|
{{
|
||||||
scope.row.CopyUserTypeList.length > 0
|
scope.row.CopyUserTypeList.length > 0
|
||||||
? scope.row.CopyUserTypeList.map((v) => $fd('UserType', v)).join(
|
? scope.row.CopyUserTypeList.map((v) => $fd('UserType', v)).join(
|
||||||
'、'
|
'、'
|
||||||
)
|
)
|
||||||
: ''
|
: ''
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 加急状态 -->
|
<!-- 加急状态 -->
|
||||||
<el-table-column prop="EmailUrgentEnum" :label="$t('dictionary:email:label:IsUrgent')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="110">
|
prop="EmailUrgentEnum"
|
||||||
|
:label="$t('dictionary:email:label:IsUrgent')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="110"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('EmailUrgent', scope.row.EmailUrgentEnum) }}
|
{{ $fd('EmailUrgent', scope.row.EmailUrgentEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 发送周期和时间 -->
|
<!-- 发送周期和时间 -->
|
||||||
<el-table-column prop="EmailCron" :label="$t('trials:emailManageCfg:table:EmailCron')" sortable="custom"
|
<el-table-column
|
||||||
show-overflow-tooltip min-width="180" />
|
prop="EmailCron"
|
||||||
|
:label="$t('trials:emailManageCfg:table:EmailCron')"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="180"
|
||||||
|
/>
|
||||||
<!-- 附件 -->
|
<!-- 附件 -->
|
||||||
<el-table-column prop="FileName" :label="$t('trials:emailManageCfg:title:fileName')" show-overflow-tooltip
|
<el-table-column
|
||||||
min-width="100" v-if="!systemLevel">
|
prop="FileName"
|
||||||
|
:label="$t('trials:emailManageCfg:title:fileName')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="100"
|
||||||
|
v-if="!systemLevel"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button v-if="scope.row.FilePath" type="text" @click="handlePreview(scope.row.FilePath)">
|
<el-button
|
||||||
|
v-if="scope.row.FilePath"
|
||||||
|
type="text"
|
||||||
|
@click="handlePreview(scope.row.FilePath)"
|
||||||
|
>
|
||||||
{{ scope.row.FileName }}
|
{{ scope.row.FileName }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 是否需要回执 -->
|
<!-- 是否需要回执 -->
|
||||||
<el-table-column prop="IsReturnRequired" :label="$t('trials:emailManageCfg:title:isReturnRequired')"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" min-width="160" v-if="!systemLevel">
|
prop="IsReturnRequired"
|
||||||
|
:label="$t('trials:emailManageCfg:title:isReturnRequired')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
v-if="!systemLevel"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsReturnRequired" type="danger">
|
<el-tag v-if="scope.row.IsReturnRequired" type="danger">
|
||||||
{{ $fd('YesOrNo', scope.row.IsReturnRequired) }}
|
{{ $fd('YesOrNo', scope.row.IsReturnRequired) }}
|
||||||
|
|
@ -168,8 +327,14 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 是否自动发送 -->
|
<!-- 是否自动发送 -->
|
||||||
<el-table-column prop="IsAutoSend" :label="$t('trials:emailManageCfg:title:isAutoSend')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="160" v-if="!systemLevel">
|
prop="IsAutoSend"
|
||||||
|
:label="$t('trials:emailManageCfg:title:isAutoSend')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
v-if="!systemLevel"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsAutoSend" type="danger">
|
<el-tag v-if="scope.row.IsAutoSend" type="danger">
|
||||||
{{ $fd('YesOrNo', scope.row.IsAutoSend) }}
|
{{ $fd('YesOrNo', scope.row.IsAutoSend) }}
|
||||||
|
|
@ -179,8 +344,14 @@
|
||||||
}}</el-tag>
|
}}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="IsEnable" :label="$t('trials:emailManageCfg:table:IsEnable')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="160" v-if="!systemLevel">
|
prop="IsEnable"
|
||||||
|
:label="$t('trials:emailManageCfg:table:IsEnable')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
v-if="!systemLevel"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsEnable" type="danger">
|
<el-tag v-if="scope.row.IsEnable" type="danger">
|
||||||
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
||||||
|
|
@ -191,12 +362,22 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 更新时间 -->
|
<!-- 更新时间 -->
|
||||||
<el-table-column prop="UpdateTime" :label="$t('trials:emailManageCfg:title:updateTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="160" />
|
prop="UpdateTime"
|
||||||
|
:label="$t('trials:emailManageCfg:title:updateTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
<!-- 创建时间 -->
|
<!-- 创建时间 -->
|
||||||
<el-table-column prop="CreateTime" :label="$t('trials:emailManageCfg:title:createTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="160" />
|
prop="CreateTime"
|
||||||
<el-table-column :label="$t('common:action:action')" min-width="180" fixed="right">
|
:label="$t('trials:emailManageCfg:title:createTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column label="Action" min-width="180" fixed="right">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" @click="handleEdit(scope.row)">
|
<el-button type="text" @click="handleEdit(scope.row)">
|
||||||
{{ $t('common:button:edit') }}
|
{{ $t('common:button:edit') }}
|
||||||
|
|
@ -205,38 +386,77 @@
|
||||||
<el-button type="text" @click="handleDelete(scope.row)">
|
<el-button type="text" @click="handleDelete(scope.row)">
|
||||||
{{ $t('common:button:delete') }}
|
{{ $t('common:button:delete') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="text" @click="
|
<el-button
|
||||||
preview(scope.row.EmailHtmlContentCN, scope.row.EmailHtmlContent)
|
type="text"
|
||||||
">{{ $t('common:button:preview') }}</el-button>
|
@click="
|
||||||
|
preview(scope.row.EmailHtmlContentCN, scope.row.EmailHtmlContent)
|
||||||
|
"
|
||||||
|
>{{ $t('common:button:preview') }}</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<!-- 分页组件 -->
|
<!-- 分页组件 -->
|
||||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination
|
||||||
@pagination="getList" />
|
class="page"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="searchData.PageIndex"
|
||||||
|
:limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
<!-- 搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<!-- 修改受试者状态 -->
|
<!-- 修改受试者状态 -->
|
||||||
<el-dialog v-if="editVisible" :visible.sync="editVisible" :close-on-click-modal="false" :title="title" width="700px"
|
<el-dialog
|
||||||
fullscreen custom-class="base-dialog-wrapper">
|
v-if="editVisible"
|
||||||
<EmailForm :data="rowData" :system-level="systemLevel" :isDistinguishCriteria="isDistinguishCriteria"
|
:visible.sync="editVisible"
|
||||||
@closeDialog="closeDialog" @getList="getList" @PreviewHTML="preview" />
|
:close-on-click-modal="false"
|
||||||
|
:title="title"
|
||||||
|
width="700px"
|
||||||
|
fullscreen
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
|
<EmailForm
|
||||||
|
:data="rowData"
|
||||||
|
:system-level="systemLevel"
|
||||||
|
:isDistinguishCriteria="isDistinguishCriteria"
|
||||||
|
@closeDialog="closeDialog"
|
||||||
|
@getList="getList"
|
||||||
|
@PreviewHTML="preview"
|
||||||
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 修改受试者状态 -->
|
<!-- 修改受试者状态 -->
|
||||||
<el-dialog v-if="attachmentVisible" :visible.sync="attachmentVisible" :close-on-click-modal="false"
|
<el-dialog
|
||||||
:title="$t('trials:emailManageCfg:title:fileName')" width="80%" custom-class="base-dialog-wrapper" append-to-body>
|
v-if="attachmentVisible"
|
||||||
<AttachmentList :business-scenario-enum="rowData.BusinessScenarioEnum"
|
:visible.sync="attachmentVisible"
|
||||||
:is-distinguish-criteria="rowData.IsDistinguishCriteria" @getList="getList" />
|
:close-on-click-modal="false"
|
||||||
|
:title="$t('trials:emailManageCfg:title:fileName')"
|
||||||
|
width="80%"
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<AttachmentList
|
||||||
|
:business-scenario-enum="rowData.BusinessScenarioEnum"
|
||||||
|
:is-distinguish-criteria="rowData.IsDistinguishCriteria"
|
||||||
|
@getList="getList"
|
||||||
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- 预览模板 -->
|
<!-- 预览模板 -->
|
||||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :close-on-click-modal="false"
|
<el-dialog
|
||||||
:title="$t('common:button:preview')" fullscreen custom-class="base-dialog-wrapper">
|
v-if="previewVisible"
|
||||||
<div style="
|
:visible.sync="previewVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
:title="$t('common:button:preview')"
|
||||||
|
fullscreen
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
style="
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: space-around;
|
justify-content: space-around;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
">
|
"
|
||||||
|
>
|
||||||
<div style="min-width: 50%">
|
<div style="min-width: 50%">
|
||||||
<!-- 邮件内容模版(CN) -->
|
<!-- 邮件内容模版(CN) -->
|
||||||
<h3>{{ $t('dictionary:email:title:title1') }}</h3>
|
<h3>{{ $t('dictionary:email:title:title1') }}</h3>
|
||||||
|
|
@ -410,8 +630,3 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
|
||||||
.box-body .search .base-search-form .el-form-item {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
|
||||||
|
|
@ -1,41 +1,85 @@
|
||||||
<template>
|
<template>
|
||||||
<base-model :config="config">
|
<base-model :config="config">
|
||||||
<div slot="dialog-body">
|
<div slot="dialog-body">
|
||||||
<el-form ref="fileForm" :model="form" label-width="100px" size="small" :rules="rules">
|
<el-form
|
||||||
|
ref="fileForm"
|
||||||
|
:model="form"
|
||||||
|
label-width="100px"
|
||||||
|
size="small"
|
||||||
|
:rules="rules"
|
||||||
|
>
|
||||||
<div class="base-dialog-body">
|
<div class="base-dialog-body">
|
||||||
<el-form-item :label="$t('dictionary:file:form:name')" prop="Name">
|
<el-form-item :label="$t('dictionary:file:form:name')" prop="Name">
|
||||||
<el-input v-model="form.Name" />
|
<el-input v-model="form.Name" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:form:nameCN')" prop="NameCN">
|
<el-form-item
|
||||||
|
:label="$t('dictionary:file:form:nameCN')"
|
||||||
|
prop="NameCN"
|
||||||
|
>
|
||||||
<el-input v-model="form.NameCN" />
|
<el-input v-model="form.NameCN" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:browser:form:ArchiveTypeEnum')" prop="ArchiveTypeEnum">
|
<el-form-item
|
||||||
<el-select v-model="form.ArchiveTypeEnum" clearable placeholder="" style="width: 100%">
|
:label="$t('dictionary:browser:form:ArchiveTypeEnum')"
|
||||||
<el-option v-for="item in $d.ArchiveType" :key="item.id" :label="item.label" :value="item.value">
|
prop="ArchiveTypeEnum"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="form.ArchiveTypeEnum"
|
||||||
|
clearable
|
||||||
|
placeholder=""
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.ArchiveType"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:browser:form:SubIdentificationEnum')" prop="SubIdentificationEnum">
|
<el-form-item
|
||||||
<el-select style="width: 100%" v-model="form.SubIdentificationEnum" clearable placeholder="">
|
:label="$t('dictionary:browser:form:SubIdentificationEnum')"
|
||||||
<el-option v-for="item in $d.SubIdentification" :key="item.id" :label="item.label" :value="item.value">
|
prop="SubIdentificationEnum"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
style="width: 100%"
|
||||||
|
v-model="form.SubIdentificationEnum"
|
||||||
|
clearable
|
||||||
|
placeholder=""
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.SubIdentification"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:browser:form:SysTemplateTypeEnum')" prop="SysTemplateTypeEnum">
|
<el-form-item
|
||||||
<el-select style="width: 100%" v-model="form.SysTemplateTypeEnum" clearable placeholder="">
|
:label="$t('dictionary:file:form:ShowOrder')"
|
||||||
<el-option v-for="item in $d.SysTemplateType" :key="item.id" :label="item.label" :value="item.value">
|
prop="ShowOrder"
|
||||||
</el-option>
|
>
|
||||||
</el-select>
|
<el-input-number
|
||||||
</el-form-item>
|
v-model="form.ShowOrder"
|
||||||
<el-form-item :label="$t('dictionary:file:form:ShowOrder')" prop="ShowOrder">
|
:step="1"
|
||||||
<el-input-number v-model="form.ShowOrder" :step="1" step-strictly></el-input-number>
|
step-strictly
|
||||||
|
></el-input-number>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:form:IsEnable')">
|
<el-form-item :label="$t('dictionary:file:form:IsEnable')">
|
||||||
<el-switch v-model="form.IsEnable" :active-value="true" :inactive-value="false">
|
<el-switch
|
||||||
|
v-model="form.IsEnable"
|
||||||
|
:active-value="true"
|
||||||
|
:inactive-value="false"
|
||||||
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:form:IsConfirmRecord')">
|
<el-form-item :label="$t('dictionary:file:form:IsConfirmRecord')">
|
||||||
<el-switch v-model="form.IsConfirmRecord" :active-value="true" :inactive-value="false">
|
<el-switch
|
||||||
|
v-model="form.IsConfirmRecord"
|
||||||
|
:active-value="true"
|
||||||
|
:inactive-value="false"
|
||||||
|
>
|
||||||
</el-switch>
|
</el-switch>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -51,7 +95,7 @@
|
||||||
</div>
|
</div>
|
||||||
</base-model>
|
</base-model>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import baseModel from '@/components/BaseModel'
|
import baseModel from '@/components/BaseModel'
|
||||||
import { addOrUpdateSysFileType } from '@/api/dictionary'
|
import { addOrUpdateSysFileType } from '@/api/dictionary'
|
||||||
export default {
|
export default {
|
||||||
|
|
@ -82,7 +126,6 @@ export default {
|
||||||
NameCN: null,
|
NameCN: null,
|
||||||
SubIdentificationEnum: null,
|
SubIdentificationEnum: null,
|
||||||
ShowOrder: 0,
|
ShowOrder: 0,
|
||||||
SysTemplateTypeEnum: null
|
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
Name: [
|
Name: [
|
||||||
|
|
@ -106,13 +149,6 @@ export default {
|
||||||
trigger: ['blur', 'change'],
|
trigger: ['blur', 'change'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
SysTemplateTypeEnum: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: this.$t('common:ruleMessage:select'),
|
|
||||||
trigger: ['blur', 'change'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
ArchiveTypeEnum: [
|
ArchiveTypeEnum: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
|
|
|
||||||
|
|
@ -11,41 +11,85 @@
|
||||||
<el-input v-model="searchData.NameCN" style="width: 100px" />
|
<el-input v-model="searchData.NameCN" style="width: 100px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:search:archiveTypeEnum')">
|
<el-form-item :label="$t('dictionary:file:search:archiveTypeEnum')">
|
||||||
<el-select v-model="searchData.ArchiveTypeEnum" clearable placeholder="" style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item in $d.ArchiveType" :key="item.id" :label="item.label" :value="item.value">
|
v-model="searchData.ArchiveTypeEnum"
|
||||||
|
clearable
|
||||||
|
placeholder=""
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.ArchiveType"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:search:subIdentificationEnum')">
|
<el-form-item
|
||||||
<el-select v-model="searchData.SubIdentificationEnum" clearable placeholder="" style="width: 100px">
|
:label="$t('dictionary:file:search:subIdentificationEnum')"
|
||||||
<el-option v-for="item in $d.SubIdentification" :key="item.id" :label="item.label" :value="item.value">
|
>
|
||||||
</el-option>
|
<el-select
|
||||||
</el-select>
|
v-model="searchData.SubIdentificationEnum"
|
||||||
</el-form-item>
|
clearable
|
||||||
<el-form-item :label="$t('dictionary:file:search:SysTemplateTypeEnum')">
|
placeholder=""
|
||||||
<el-select v-model="searchData.SysTemplateTypeEnum" clearable placeholder="" style="width: 100px">
|
style="width: 100px"
|
||||||
<el-option v-for="item in $d.SysTemplateType" :key="item.id" :label="item.label" :value="item.value">
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.SubIdentification"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:search:isEnable')">
|
<el-form-item :label="$t('dictionary:file:search:isEnable')">
|
||||||
<el-select v-model="searchData.IsEnable" clearable placeholder="" style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item in $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value">
|
v-model="searchData.IsEnable"
|
||||||
|
clearable
|
||||||
|
placeholder=""
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.YesOrNo"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('dictionary:file:search:isConfirmRecord')">
|
<el-form-item :label="$t('dictionary:file:search:isConfirmRecord')">
|
||||||
<el-select v-model="searchData.IsConfirmRecord" clearable placeholder="" style="width: 100px">
|
<el-select
|
||||||
<el-option v-for="item in $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value">
|
v-model="searchData.IsConfirmRecord"
|
||||||
|
clearable
|
||||||
|
placeholder=""
|
||||||
|
style="width: 100px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.YesOrNo"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-search"
|
||||||
|
@click="handleSearch"
|
||||||
|
>
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="handleReset"
|
||||||
|
>
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -57,60 +101,106 @@
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" :data="list" stripe height="100"
|
<el-table
|
||||||
style="width: 100%" @sort-change="handleSortByColumn">
|
v-loading="loading"
|
||||||
|
v-adaptive="{ bottomOffset: 45 }"
|
||||||
|
:data="list"
|
||||||
|
stripe
|
||||||
|
height="100"
|
||||||
|
style="width: 100%"
|
||||||
|
@sort-change="handleSortByColumn"
|
||||||
|
>
|
||||||
<el-table-column type="index" width="40" />
|
<el-table-column type="index" width="40" />
|
||||||
|
|
||||||
<el-table-column prop="Name" :label="$t('dictionary:file:table:Name')" sortable="custom" show-overflow-tooltip
|
<el-table-column
|
||||||
min-width="150px" />
|
prop="Name"
|
||||||
<el-table-column prop="NameCN" :label="$t('dictionary:file:table:NameCN')" show-overflow-tooltip
|
:label="$t('dictionary:file:table:Name')"
|
||||||
sortable="custom" min-width="150px" />
|
sortable="custom"
|
||||||
<el-table-column prop="ArchiveTypeEnum" :label="$t('dictionary:file:table:archiveTypeEnum')"
|
show-overflow-tooltip
|
||||||
show-overflow-tooltip sortable="custom" min-width="120px">
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="NameCN"
|
||||||
|
:label="$t('dictionary:file:table:NameCN')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="ArchiveTypeEnum"
|
||||||
|
:label="$t('dictionary:file:table:archiveTypeEnum')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('ArchiveType', scope.row.ArchiveTypeEnum) }}
|
{{ $fd('ArchiveType', scope.row.ArchiveTypeEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="SubIdentificationEnum" :label="$t('dictionary:file:table:subIdentificationEnum')"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" min-width="120px">
|
prop="SubIdentificationEnum"
|
||||||
|
:label="$t('dictionary:file:table:subIdentificationEnum')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('SubIdentification', scope.row.SubIdentificationEnum) }}
|
{{ $fd('SubIdentification', scope.row.SubIdentificationEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="SysTemplateTypeEnum" :label="$t('dictionary:file:table:SysTemplateTypeEnum')"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom">
|
prop="ShowOrder"
|
||||||
<template slot-scope="scope">
|
:label="$t('dictionary:file:table:ShowOrder')"
|
||||||
{{ $fd('SysTemplateType', scope.row.SysTemplateTypeEnum) }}
|
show-overflow-tooltip
|
||||||
</template>
|
sortable="custom"
|
||||||
</el-table-column>
|
/>
|
||||||
<el-table-column prop="ShowOrder" :label="$t('dictionary:file:table:ShowOrder')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
:label="$t('dictionary:file:table:IsEnable')"
|
||||||
<el-table-column :label="$t('dictionary:file:table:IsEnable')" prop="IsEnable" show-overflow-tooltip
|
prop="IsEnable"
|
||||||
sortable="custom" min-width="120px">
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="!scope.row.IsEnable ? 'info' : ''">
|
<el-tag :type="!scope.row.IsEnable ? 'info' : ''">
|
||||||
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('dictionary:file:table:isConfirmRecord')" prop="IsConfirmRecord"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" min-width="150px">
|
:label="$t('dictionary:file:table:isConfirmRecord')"
|
||||||
|
prop="IsConfirmRecord"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
width="200"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="!scope.row.IsEnable ? 'info' : ''">
|
<el-tag :type="!scope.row.IsEnable ? 'info' : ''">
|
||||||
{{ $fd('YesOrNo', scope.row.IsConfirmRecord) }}
|
{{ $fd('YesOrNo', scope.row.IsConfirmRecord) }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column prop="CreateTime" :label="$t('dictionary:file:table:createTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" min-width="180px" />
|
prop="CreateTime"
|
||||||
<el-table-column prop="UpdateTime" :label="$t('dictionary:file:table:updateTime')" show-overflow-tooltip
|
:label="$t('dictionary:file:table:createTime')"
|
||||||
sortable="custom" min-width="180px" />
|
show-overflow-tooltip
|
||||||
<el-table-column :label="$t('dictionary:file:table:action')" width="200" fixed="right">
|
sortable="custom"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="UpdateTime"
|
||||||
|
:label="$t('dictionary:file:table:updateTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('dictionary:file:table:action')"
|
||||||
|
width="200"
|
||||||
|
fixed="right"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button type="text" @click="handleEdit(scope.row)">
|
<el-button type="text" @click="handleEdit(scope.row)">
|
||||||
{{ $t('dictionary:file:button:edit') }}
|
{{ $t('dictionary:file:button:edit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="text" @click="handleDelete(scope.row)" v-if="hasPermi(['dictionary:template:file:del'])">
|
<el-button
|
||||||
|
type="text"
|
||||||
|
@click="handleDelete(scope.row)"
|
||||||
|
v-if="hasPermi(['dictionary:template:file:del'])"
|
||||||
|
>
|
||||||
{{ $t('dictionary:file:button:delete') }}
|
{{ $t('dictionary:file:button:delete') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -118,9 +208,20 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页组件 -->
|
<!-- 分页组件 -->
|
||||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination
|
||||||
@pagination="getList" />
|
class="page"
|
||||||
<File-form :config="config" :data="rowData" v-if="config.visible" @close="close" @getList="getList" />
|
:total="total"
|
||||||
|
:page.sync="searchData.PageIndex"
|
||||||
|
:limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
|
<File-form
|
||||||
|
:config="config"
|
||||||
|
:data="rowData"
|
||||||
|
v-if="config.visible"
|
||||||
|
@close="close"
|
||||||
|
@getList="getList"
|
||||||
|
/>
|
||||||
</box-content>
|
</box-content>
|
||||||
</BoxContent>
|
</BoxContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -137,7 +238,6 @@ const searchDataDefault = () => {
|
||||||
Name: null,
|
Name: null,
|
||||||
NameCN: null,
|
NameCN: null,
|
||||||
SubIdentificationEnum: null,
|
SubIdentificationEnum: null,
|
||||||
SysTemplateTypeEnum: null,
|
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
PageSize: 20,
|
PageSize: 20,
|
||||||
asc: false,
|
asc: false,
|
||||||
|
|
@ -244,7 +344,4 @@ export default {
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.box-body .search .base-search-form .el-form-item {
|
|
||||||
margin-bottom: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
@ -9,36 +9,71 @@
|
||||||
<!-- Reset Password -->
|
<!-- Reset Password -->
|
||||||
|
|
||||||
<div class="box-wrapper" v-if="active === 0">
|
<div class="box-wrapper" v-if="active === 0">
|
||||||
<el-form ref="resetForm" v-loading="formLoading" :model="form" label-width="130px" :rules="rules"
|
<el-form
|
||||||
class="demo-ruleForm" size="small">
|
ref="resetForm"
|
||||||
|
v-loading="formLoading"
|
||||||
|
:model="form"
|
||||||
|
label-width="130px"
|
||||||
|
:rules="rules"
|
||||||
|
class="demo-ruleForm"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
<!-- 邮箱 -->
|
<!-- 邮箱 -->
|
||||||
<el-form-item :label="$t('passwordReset:form:email')" prop="EmailOrPhone">
|
<el-form-item
|
||||||
|
:label="$t('passwordReset:form:email')"
|
||||||
|
prop="EmailOrPhone"
|
||||||
|
>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-input v-model="form.EmailOrPhone" autocomplete="off" @change="handleEmailChange" />
|
<el-input
|
||||||
|
v-model="form.EmailOrPhone"
|
||||||
|
autocomplete="off"
|
||||||
|
@change="handleEmailChange"
|
||||||
|
/>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 验证码 -->
|
<!-- 验证码 -->
|
||||||
<el-form-item :label="$t('trials:researchForm:form:verifyCode')" required>
|
<el-form-item
|
||||||
|
:label="$t('trials:researchForm:form:verifyCode')"
|
||||||
|
required
|
||||||
|
>
|
||||||
<el-col :span="18">
|
<el-col :span="18">
|
||||||
<el-form-item prop="VerificationCode">
|
<el-form-item prop="VerificationCode">
|
||||||
<el-input v-model="form.VerificationCode" autocomplete="off" />
|
<el-input v-model="form.VerificationCode" autocomplete="off" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="6" style="text-align: right">
|
<el-col :span="6" style="text-align: right">
|
||||||
<el-button size="small" type="primary" style="width: 80%" :disabled="sendDisabled"
|
<el-button
|
||||||
@click="handleSendCode">{{ sendTitle }}</el-button>
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
style="width: 80%"
|
||||||
|
:disabled="sendDisabled"
|
||||||
|
@click="handleSendCode"
|
||||||
|
>{{ sendTitle }}</el-button
|
||||||
|
>
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<!-- 校验 -->
|
<!-- 校验 -->
|
||||||
<el-button size="small" type="primary" style="width: 50%; margin: auto; display: block"
|
<el-button
|
||||||
:disabled="form.VerificationCode === '' || form.EmailOrPhone === ''" @click="verifyCode">
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
style="width: 50%; margin: auto; display: block"
|
||||||
|
:disabled="form.VerificationCode === '' || form.EmailOrPhone === ''"
|
||||||
|
@click="verifyCode"
|
||||||
|
>
|
||||||
{{ $t('passwordReset:button:verify') }}
|
{{ $t('passwordReset:button:verify') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="box-wrapper" v-show="active === 1">
|
<div class="box-wrapper" v-show="active === 1">
|
||||||
<el-form ref="resetForm2" v-loading="formLoading" :model="form"
|
<el-form
|
||||||
:label-width="$i18n.locale === 'en' ? '180px' : '100px'" :rules="rules2" class="demo-ruleForm" size="small">
|
ref="resetForm2"
|
||||||
|
v-loading="formLoading"
|
||||||
|
:model="form"
|
||||||
|
:label-width="$i18n.locale === 'en' ? '180px' : '100px'"
|
||||||
|
:rules="rules2"
|
||||||
|
class="demo-ruleForm"
|
||||||
|
size="small"
|
||||||
|
>
|
||||||
<!-- 用户名 -->
|
<!-- 用户名 -->
|
||||||
<el-form-item :label="$t('passwordReset:form:userName')" prop="UserId">
|
<el-form-item :label="$t('passwordReset:form:userName')" prop="UserId">
|
||||||
<el-input v-model="form.UserName" disabled />
|
<el-input v-model="form.UserName" disabled />
|
||||||
|
|
@ -70,17 +105,27 @@
|
||||||
<el-input v-model="form.UserType" disabled />
|
<el-input v-model="form.UserType" disabled />
|
||||||
</el-form-item> -->
|
</el-form-item> -->
|
||||||
<!-- 新密码 -->
|
<!-- 新密码 -->
|
||||||
<el-form-item class="my_new_pwd" :label="$t('passwordReset:form:password')" prop="NewPwd"
|
<el-form-item
|
||||||
style="position: relative">
|
class="my_new_pwd"
|
||||||
|
:label="$t('passwordReset:form:password')"
|
||||||
|
prop="NewPwd"
|
||||||
|
style="position: relative"
|
||||||
|
>
|
||||||
<el-input v-model="form.NewPwd" show-password autocomplete="off" />
|
<el-input v-model="form.NewPwd" show-password autocomplete="off" />
|
||||||
<span style="position: absolute; right: -30px">
|
<span style="position: absolute; right: -30px">
|
||||||
<el-tooltip :content="$t('passwordReset:form:passwordCentent')" placement="top">
|
<el-tooltip
|
||||||
|
:content="$t('passwordReset:form:passwordCentent')"
|
||||||
|
placement="top"
|
||||||
|
>
|
||||||
<i class="el-icon-question" />
|
<i class="el-icon-question" />
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
</span>
|
</span>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 确认密码 -->
|
<!-- 确认密码 -->
|
||||||
<el-form-item :label="$t('passwordReset:form:confirmPassword')" prop="CheckPass">
|
<el-form-item
|
||||||
|
:label="$t('passwordReset:form:confirmPassword')"
|
||||||
|
prop="CheckPass"
|
||||||
|
>
|
||||||
<el-input v-model="form.CheckPass" show-password autocomplete="off" />
|
<el-input v-model="form.CheckPass" show-password autocomplete="off" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
@ -90,7 +135,12 @@
|
||||||
{{ $t('passwordReset:button:cancel') }}
|
{{ $t('passwordReset:button:cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 提交 -->
|
<!-- 提交 -->
|
||||||
<el-button size="small" type="primary" @click="onSubmit" style="width: 46%">
|
<el-button
|
||||||
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
@click="onSubmit"
|
||||||
|
style="width: 46%"
|
||||||
|
>
|
||||||
{{ $t('passwordReset:button:submit') }}
|
{{ $t('passwordReset:button:submit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -338,14 +388,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onCancel() {
|
onCancel() {
|
||||||
// this.$refs['resetForm'].resetFields()
|
this.$refs['resetForm'].resetFields()
|
||||||
Object.keys(this.form).forEach((key) => {
|
Object.keys(this.form).forEach((key) => {
|
||||||
this.form[key] = ''
|
this.form[key] = ''
|
||||||
})
|
})
|
||||||
this.sendDisabled = false
|
|
||||||
this.sendTitle = this.$t('passwordReset:button:send')
|
|
||||||
countdown = 60
|
|
||||||
clearTimeout(timer)
|
|
||||||
this.active = 0
|
this.active = 0
|
||||||
},
|
},
|
||||||
goBack() {
|
goBack() {
|
||||||
|
|
@ -358,14 +404,12 @@ export default {
|
||||||
.reset-wrapper {
|
.reset-wrapper {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-wrapper .el-page-header {
|
.reset-wrapper .el-page-header {
|
||||||
line-height: 50px;
|
line-height: 50px;
|
||||||
border: 1px solid #ebeef5;
|
border: 1px solid #ebeef5;
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
.reset-wrapper .box-wrapper {
|
.reset-wrapper .box-wrapper {
|
||||||
width: 700px;
|
width: 700px;
|
||||||
margin: 20px auto;
|
margin: 20px auto;
|
||||||
|
|
@ -381,7 +425,6 @@ export default {
|
||||||
.is-error.my_new_pwd {
|
.is-error.my_new_pwd {
|
||||||
margin-bottom: 45px;
|
margin-bottom: 45px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.flexBox {
|
.flexBox {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
|
||||||
|
|
@ -2,76 +2,152 @@
|
||||||
<div class="log">
|
<div class="log">
|
||||||
<div ref="leftContainer" class="left">
|
<div ref="leftContainer" class="left">
|
||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<el-form-item :label="$t('system:loginLog:label:OptType')" prop="OptType">
|
<el-form-item
|
||||||
<el-select v-model="searchData.OptTypeList" clearable style="width: 200px" multiple :collapse-tags="true">
|
:label="$t('system:loginLog:label:OptType')"
|
||||||
<el-option v-for="item of $d.UserOptType" :key="'UserOptType' + item.label" :value="item.value"
|
prop="OptType"
|
||||||
:label="item.label" />
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.OptType"
|
||||||
|
clearable
|
||||||
|
style="width: 120px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.UserOptType"
|
||||||
|
:key="'UserOptType' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="IP" prop="IP">
|
<el-form-item label="IP" prop="IP">
|
||||||
<el-input v-model="searchData.IP" size="small" clearable style="width: 120px" />
|
<el-input
|
||||||
|
v-model="searchData.IP"
|
||||||
|
size="small"
|
||||||
|
clearable
|
||||||
|
style="width: 120px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('system:loginLog:label:LoginFaildName')" prop="LoginFaildName">
|
<el-form-item
|
||||||
<el-input v-model="searchData.LoginFaildName" size="small" clearable style="width: 120px" />
|
:label="$t('system:loginLog:label:LoginFaildName')"
|
||||||
|
prop="LoginFaildName"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="searchData.LoginFaildName"
|
||||||
|
size="small"
|
||||||
|
clearable
|
||||||
|
style="width: 120px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('system:loginLog:table:LoginUserName')" prop="LoginFaildName">
|
<el-form-item
|
||||||
<el-input v-model="searchData.LoginUserName" size="small" clearable style="width: 120px" />
|
: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>
|
||||||
<!-- <el-form-item :label="$t('system:loginLog:table:LoginUserType')" prop="LoginUserTypeEnum">
|
<el-form-item
|
||||||
<el-select v-model="searchData.LoginUserTypeEnum" clearable style="width: 120px">
|
:label="$t('system:loginLog:table:LoginUserType')"
|
||||||
<el-option v-for="item of $d.UserType" :key="'UserType' + item.label" :value="item.value"
|
prop="LoginUserTypeEnum"
|
||||||
:label="item.label" />
|
>
|
||||||
</el-select>
|
<el-select
|
||||||
</el-form-item> -->
|
v-model="searchData.LoginUserTypeEnum"
|
||||||
<el-form-item :label="$t('system:loginLog:label:IsLoginUncommonly')" prop="IsLoginUncommonly ">
|
clearable
|
||||||
<el-select v-model="searchData.IsLoginUncommonly" clearable style="width: 120px">
|
style="width: 120px"
|
||||||
<el-option v-for="item of $d.YesOrNo" :key="item.id" :value="item.value" :label="item.label" />
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.UserType"
|
||||||
|
:key="'UserType' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('system:loginLog:label:CreateTime')">
|
<el-form-item :label="$t('system:loginLog:label:CreateTime')">
|
||||||
<el-date-picker v-model="datetimerange" type="datetimerange" value-format="yyyy-MM-dd HH:mm:ss"
|
<el-date-picker
|
||||||
:default-time="['00:00:00', '23:59:59']" @change="handleDatetimeChange" style="width: 380px" />
|
v-model="datetimerange"
|
||||||
|
type="datetimerange"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
@change="handleDatetimeChange"
|
||||||
|
style="width: 380px"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" icon="el-icon-search" @click="getList">
|
<el-button type="primary" icon="el-icon-search" @click="getList">
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="handleReset"
|
||||||
|
>
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" height="100" :data="list" class="table"
|
<el-table
|
||||||
@sort-change="handleSortByColumn">
|
v-loading="loading"
|
||||||
|
v-adaptive="{ bottomOffset: 45 }"
|
||||||
|
height="100"
|
||||||
|
:data="list"
|
||||||
|
class="table"
|
||||||
|
@sort-change="handleSortByColumn"
|
||||||
|
>
|
||||||
<el-table-column type="index" width="50">
|
<el-table-column type="index" width="50">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span style="
|
<span
|
||||||
|
style="
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
">
|
"
|
||||||
<el-tooltip class="item" effect="dark" :content="$t('system:loginLog:label:IsLoginUncommonly')"
|
>
|
||||||
placement="top" style="margin-right: 3px" v-if="scope.row.IsIgnoreUncommonly">
|
<el-tooltip
|
||||||
<i v-if="scope.row.IsLoginUncommonly" class="el-icon-warning icon-i icon-success"></i>
|
class="item"
|
||||||
</el-tooltip>
|
effect="dark"
|
||||||
<el-tooltip class="item" effect="dark" :content="$t('system:loginLog:label:IsLoginUncommonly')"
|
:content="$t('system:loginLog:label:IsLoginUncommonly')"
|
||||||
placement="top" style="margin-right: 3px" v-else-if="scope.row.IsLoginUncommonly">
|
placement="top"
|
||||||
<i v-if="scope.row.IsLoginUncommonly" class="el-icon-warning icon-i"
|
style="margin-right: 3px"
|
||||||
@click.stop="setIsIgnoreUncommonly(scope.row)"></i>
|
v-if="scope.row.IsLoginUncommonly"
|
||||||
|
>
|
||||||
|
<i
|
||||||
|
v-if="scope.row.IsLoginUncommonly"
|
||||||
|
class="el-icon-warning icon-i"
|
||||||
|
></i>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<span>{{ scope.$index + 1 }}</span>
|
<span>{{ scope.$index + 1 }}</span>
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('system:loginLog:table:OptType')" prop="OptType" min-width="150"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom">
|
:label="$t('system:loginLog:table:OptType')"
|
||||||
|
prop="OptType"
|
||||||
|
min-width="150"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd('UserOptType', scope.row.OptType) }}
|
{{ $fd('UserOptType', scope.row.OptType) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column label="IP" prop="IP" min-width="150" sortable="custom" show-overflow-tooltip />
|
<el-table-column
|
||||||
<el-table-column :label="$t('trials:loginLog:table:IPRegion')" prop="IPRegion" min-width="120"
|
label="IP"
|
||||||
show-overflow-tooltip sortable="custom" />
|
prop="IP"
|
||||||
|
min-width="150"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('trials:loginLog:table:IPRegion')"
|
||||||
|
prop="IPRegion"
|
||||||
|
min-width="120"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<!-- <el-table-column
|
<!-- <el-table-column
|
||||||
:label="$t('system:loginLog:table:LoginFaildName')"
|
:label="$t('system:loginLog:table:LoginFaildName')"
|
||||||
prop="LoginFaildName"
|
prop="LoginFaildName"
|
||||||
|
|
@ -79,10 +155,20 @@
|
||||||
show-overflow-tooltip
|
show-overflow-tooltip
|
||||||
sortable="custom"
|
sortable="custom"
|
||||||
/> -->
|
/> -->
|
||||||
<el-table-column :label="$t('system:loginLog:table:LoginUserName')" prop="ActionUserName" min-width="140"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" />
|
:label="$t('system:loginLog:table:LoginUserName')"
|
||||||
<el-table-column :label="$t('system:loginLog:table:Aetionlserlype')" prop="ActionUserType" min-width="100"
|
prop="ActionUserName"
|
||||||
show-overflow-tooltip sortable="custom" />
|
min-width="140"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('system:loginLog:table:Aetionlserlype')"
|
||||||
|
prop="ActionUserType"
|
||||||
|
min-width="100"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<!-- <el-table-column
|
<!-- <el-table-column
|
||||||
:label="$t('system:loginLog:table:LoginUserType')"
|
:label="$t('system:loginLog:table:LoginUserType')"
|
||||||
prop="LoginUserTypeEnum"
|
prop="LoginUserTypeEnum"
|
||||||
|
|
@ -94,8 +180,13 @@
|
||||||
{{ $fd("UserType", scope.row.LoginUserTypeEnum) }}
|
{{ $fd("UserType", scope.row.LoginUserTypeEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<el-table-column :label="$t('system:loginLog:table:OptUserName')" prop="TargetIdentityUserName" min-width="200"
|
<el-table-column
|
||||||
sortable="custom" show-overflow-tooltip />
|
:label="$t('system:loginLog:table:OptUserName')"
|
||||||
|
prop="TargetIdentityUserName"
|
||||||
|
min-width="200"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
<!-- <el-table-column
|
<!-- <el-table-column
|
||||||
:label="$t('system:loginLog:table:OptUserType')"
|
:label="$t('system:loginLog:table:OptUserType')"
|
||||||
prop="OptUserTypeEnum"
|
prop="OptUserTypeEnum"
|
||||||
|
|
@ -107,36 +198,51 @@
|
||||||
{{ $fd("UserType", scope.row.OptUserTypeEnum) }}
|
{{ $fd("UserType", scope.row.OptUserTypeEnum) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column> -->
|
</el-table-column> -->
|
||||||
<el-table-column :label="$t('system:loginLog:table:detail')" min-width="120" show-overflow-tooltip>
|
<el-table-column
|
||||||
|
:label="$t('system:loginLog:table:detail')"
|
||||||
|
min-width="120"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button v-if="scope.row.JsonObj" type="text" @click="handleOpenDialog(scope.row)">
|
<el-button
|
||||||
|
v-if="scope.row.JsonObj"
|
||||||
|
type="text"
|
||||||
|
@click="handleOpenDialog(scope.row)"
|
||||||
|
>
|
||||||
<span>{{ $t('system:loginLog:message:detail') }}</span>
|
<span>{{ $t('system:loginLog:message:detail') }}</span>
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column :label="$t('system:loginLog:table:CreateTime')" prop="CreateTime" min-width="180"
|
<el-table-column
|
||||||
sortable="custom" show-overflow-tooltip />
|
:label="$t('system:loginLog:table:CreateTime')"
|
||||||
|
prop="CreateTime"
|
||||||
|
min-width="180"
|
||||||
|
sortable="custom"
|
||||||
|
show-overflow-tooltip
|
||||||
|
/>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div class="pagination" style="text-align: right; margin-top: 5px">
|
<div class="pagination" style="text-align: right; margin-top: 5px">
|
||||||
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination
|
||||||
@pagination="getList" />
|
:total="total"
|
||||||
|
:page.sync="searchData.PageIndex"
|
||||||
|
:limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<detail :config="config" :JsonObj="JsonObj" />
|
<detail :config="config" :JsonObj="JsonObj" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getUserLogList, setIsIgnoreUncommonly } from '@/api/user'
|
import { getUserLogList } from '@/api/user'
|
||||||
import Pagination from '@/components/Pagination'
|
import Pagination from '@/components/Pagination'
|
||||||
import detail from './detail.vue'
|
import detail from './detail.vue'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
const searchDataDefault = () => {
|
const searchDataDefault = () => {
|
||||||
return {
|
return {
|
||||||
OptType: null,
|
OptType: null,
|
||||||
OptTypeList: [],
|
|
||||||
Ip: '',
|
Ip: '',
|
||||||
LoginFaildName: '',
|
LoginFaildName: '',
|
||||||
IsLoginUncommonly: null,
|
|
||||||
LoginUserName: '',
|
LoginUserName: '',
|
||||||
LoginUserTypeEnum: null,
|
LoginUserTypeEnum: null,
|
||||||
BeginDate: '',
|
BeginDate: '',
|
||||||
|
|
@ -170,26 +276,6 @@ export default {
|
||||||
this.getList()
|
this.getList()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 忽略异地登录
|
|
||||||
async setIsIgnoreUncommonly(row) {
|
|
||||||
try {
|
|
||||||
let confirm = await this.$confirm(this.$t("system:loginLog:confirmMessage:setIsIgnoreUncommonly"))
|
|
||||||
if (!confirm) return false
|
|
||||||
let data = {
|
|
||||||
IsIgnoreUncommonly: true,
|
|
||||||
Id: row.Id
|
|
||||||
}
|
|
||||||
this.loading = true
|
|
||||||
let res = await setIsIgnoreUncommonly(data)
|
|
||||||
this.loading = false
|
|
||||||
if (res.IsSuccess) {
|
|
||||||
this.getList()
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
this.loading = false
|
|
||||||
console.log(err)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleOpenDialog(row) {
|
handleOpenDialog(row) {
|
||||||
if (!row.JsonObj)
|
if (!row.JsonObj)
|
||||||
return this.$message.warning(this.$t('system:loginLog:message:noJSON'))
|
return this.$message.warning(this.$t('system:loginLog:message:noJSON'))
|
||||||
|
|
@ -248,37 +334,28 @@ export default {
|
||||||
display: flex;
|
display: flex;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
|
|
||||||
.left {
|
.left {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
width: 0;
|
width: 0;
|
||||||
flex-grow: 4;
|
flex-grow: 4;
|
||||||
|
|
||||||
// border-right: 1px solid #ccc;
|
// border-right: 1px solid #ccc;
|
||||||
.filter-container {
|
.filter-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 5px;
|
margin: 5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.data-table {
|
.data-table {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 5px 0px;
|
padding: 5px 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination-container {
|
.pagination-container {
|
||||||
text-align: right;
|
text-align: right;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-i {
|
.icon-i {
|
||||||
color: #f56c6c;
|
color: #f56c6c;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-success {
|
|
||||||
color: #67C23A
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
|
|
@ -9,28 +9,64 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 研究方案号 -->
|
<!-- 研究方案号 -->
|
||||||
<el-form-item :label="$t('trials:trials-list:table:researchNumber')">
|
<el-form-item :label="$t('trials:trials-list:table:researchNumber')">
|
||||||
<el-input v-model="searchData.ResearchProgramNo" style="width: 100px" clearable />
|
<el-input
|
||||||
|
v-model="searchData.ResearchProgramNo"
|
||||||
|
style="width: 100px"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 试验名称 -->
|
<!-- 试验名称 -->
|
||||||
<el-form-item :label="$t('trials:trials-list:table:experimentName')">
|
<el-form-item :label="$t('trials:trials-list:table:experimentName')">
|
||||||
<el-input v-model="searchData.ExperimentName" style="width: 100px" clearable />
|
<el-input
|
||||||
|
v-model="searchData.ExperimentName"
|
||||||
|
style="width: 100px"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- Sponsor -->
|
<!-- Sponsor -->
|
||||||
<el-form-item :label="$t('trials:trials-list:table:sponsor')">
|
<el-form-item :label="$t('trials:trials-list:table:sponsor')">
|
||||||
<el-select v-model="searchData.SponsorId" style="width: 150px" clearable>
|
<el-select
|
||||||
<el-option v-for="item in sponsorList" :key="item.Id" :label="item.SponsorName" :value="item.Id" />
|
v-model="searchData.SponsorId"
|
||||||
|
style="width: 150px"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in sponsorList"
|
||||||
|
:key="item.Id"
|
||||||
|
:label="item.SponsorName"
|
||||||
|
:value="item.Id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 阅片标准 -->
|
<!-- 阅片标准 -->
|
||||||
<el-form-item v-if="hasPermi(['role:ir'])" :label="$t('trials:trials-list:table:IR_ReadingCriterionList')">
|
<el-form-item
|
||||||
<el-select v-model="searchData.CriterionType" style="width: 150px" clearable>
|
v-if="hasPermi(['role:ir'])"
|
||||||
<el-option v-for="item in $d.CriterionType" :key="item.id" :label="item.label" :value="item.value" />
|
:label="$t('trials:trials-list:table:IR_ReadingCriterionList')"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.CriterionType"
|
||||||
|
style="width: 150px"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in $d.CriterionType"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 联系人 -->
|
<!-- 联系人 -->
|
||||||
<el-form-item v-if="hasPermi(['role:ir'])" :label="$t('trials:trials-list:table:IR_PMEmailList')">
|
<el-form-item
|
||||||
<el-input v-model="searchData.PM_EMail" style="width: 100px" clearable />
|
v-if="hasPermi(['role:ir'])"
|
||||||
|
:label="$t('trials:trials-list:table:IR_PMEmailList')"
|
||||||
|
>
|
||||||
|
<el-input
|
||||||
|
v-model="searchData.PM_EMail"
|
||||||
|
style="width: 100px"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<!-- <el-button type="text" @click="isShow = !isShow">More</el-button> -->
|
<!-- <el-button type="text" @click="isShow = !isShow">More</el-button> -->
|
||||||
|
|
@ -39,19 +75,33 @@
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- Reset -->
|
<!-- Reset -->
|
||||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
<el-button
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
@click="handleReset"
|
||||||
|
>
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- Export -->
|
<!-- Export -->
|
||||||
<el-button v-hasPermi="['trials:trials-list:export']" type="primary" icon="el-icon-download"
|
<el-button
|
||||||
:loading="exportLoading" @click="handleExportTrial">
|
v-hasPermi="['trials:trials-list:export']"
|
||||||
|
type="primary"
|
||||||
|
icon="el-icon-download"
|
||||||
|
:loading="exportLoading"
|
||||||
|
@click="handleExportTrial"
|
||||||
|
>
|
||||||
{{ $t('common:button:export') }}
|
{{ $t('common:button:export') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<span style="margin-left: auto">
|
<span style="margin-left: auto">
|
||||||
<!-- New -->
|
<!-- New -->
|
||||||
<el-button v-hasPermi="['trials:trials-list:new']" icon="el-icon-plus" type="primary" @click="handleNew">
|
<el-button
|
||||||
|
v-hasPermi="['trials:trials-list:new']"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
type="primary"
|
||||||
|
@click="handleNew"
|
||||||
|
>
|
||||||
{{ $t('common:button:new') }}
|
{{ $t('common:button:new') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -62,88 +112,190 @@
|
||||||
<div style="padding: 10px">
|
<div style="padding: 10px">
|
||||||
<el-form label-width="140px">
|
<el-form label-width="140px">
|
||||||
<el-form-item label="Trial ID">
|
<el-form-item label="Trial ID">
|
||||||
<el-input v-model="searchData.Code" placeholder="Trial ID" style="width: 100%" clearable />
|
<el-input
|
||||||
|
v-model="searchData.Code"
|
||||||
|
placeholder="Trial ID"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Indication">
|
<el-form-item label="Indication">
|
||||||
<el-input v-model="searchData.Indication" placeholder="Indication" style="width: 100%" clearable />
|
<el-input
|
||||||
|
v-model="searchData.Indication"
|
||||||
|
placeholder="Indication"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Assessment Criteria">
|
<el-form-item label="Assessment Criteria">
|
||||||
<el-select v-model="searchData.CriterionIds" placeholder="Assessment Criteria" style="width: 100%" clearable
|
<el-select
|
||||||
multiple>
|
v-model="searchData.CriterionIds"
|
||||||
|
placeholder="Assessment Criteria"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
multiple
|
||||||
|
>
|
||||||
<!-- <el-option
|
<!-- <el-option
|
||||||
v-for="(key,value) of dictionaryList.ReadingStandard"
|
v-for="(key,value) of dictionaryList.ReadingStandard"
|
||||||
:key="key"
|
:key="key"
|
||||||
:label="key"
|
:label="key"
|
||||||
:value="value"
|
:value="value"
|
||||||
/> -->
|
/> -->
|
||||||
<el-option v-for="item of dict.type.ReadingStandard" :key="item.value" :label="item.label"
|
<el-option
|
||||||
:value="item.value" />
|
v-for="item of dict.type.ReadingStandard"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Sponsor">
|
<el-form-item label="Sponsor">
|
||||||
<el-select v-model="searchData.SponsorId" placeholder="Sponsor" style="width: 100%" clearable>
|
<el-select
|
||||||
<el-option v-for="item in sponsorList" :key="item.Id" :label="item.SponsorName" :value="item.Id" />
|
v-model="searchData.SponsorId"
|
||||||
|
placeholder="Sponsor"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in sponsorList"
|
||||||
|
:key="item.Id"
|
||||||
|
:label="item.SponsorName"
|
||||||
|
:value="item.Id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="CRO">
|
<el-form-item label="CRO">
|
||||||
<el-select v-model="searchData.CROId" placeholder="CRO" style="width: 100%" clearable>
|
<el-select
|
||||||
<el-option v-for="item of croList" :key="item.Id" :label="item.CROName" :value="item.Id" />
|
v-model="searchData.CROId"
|
||||||
|
placeholder="CRO"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of croList"
|
||||||
|
:key="item.Id"
|
||||||
|
:label="item.CROName"
|
||||||
|
:value="item.Id"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Phase">
|
<el-form-item label="Phase">
|
||||||
<el-select v-model="searchData.Phase" placeholder="Phase" style="width: 100%" clearable>
|
<el-select
|
||||||
<el-option v-for="item in phaseOptions" :key="item.value" :label="item.value" :value="item.value" />
|
v-model="searchData.Phase"
|
||||||
|
placeholder="Phase"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in phaseOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.value"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="ReviewType">
|
<el-form-item label="ReviewType">
|
||||||
<el-select v-model="searchData.ReviewTypeIds" placeholder="ReviewType" style="width: 100%" clearable
|
<el-select
|
||||||
multiple>
|
v-model="searchData.ReviewTypeIds"
|
||||||
|
placeholder="ReviewType"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
multiple
|
||||||
|
>
|
||||||
<!-- <el-option
|
<!-- <el-option
|
||||||
v-for="(key,value) of dictionaryList.ReviewType"
|
v-for="(key,value) of dictionaryList.ReviewType"
|
||||||
:key="key"
|
:key="key"
|
||||||
:label="key"
|
:label="key"
|
||||||
:value="value"
|
:value="value"
|
||||||
/> -->
|
/> -->
|
||||||
<el-option v-for="item of dict.type.ReviewType" :key="item.value" :label="item.label"
|
<el-option
|
||||||
:value="item.value" />
|
v-for="item of dict.type.ReviewType"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Modality">
|
<el-form-item label="Modality">
|
||||||
<el-select v-model="searchData.ModalityIds" multiple placeholder="Modality" style="width: 100%" clearable>
|
<el-select
|
||||||
|
v-model="searchData.ModalityIds"
|
||||||
|
multiple
|
||||||
|
placeholder="Modality"
|
||||||
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
<!-- <el-option
|
<!-- <el-option
|
||||||
v-for="(key,value) of dictionaryList.ReadingType"
|
v-for="(key,value) of dictionaryList.ReadingType"
|
||||||
:key="key"
|
:key="key"
|
||||||
:label="key"
|
:label="key"
|
||||||
:value="value"
|
:value="value"
|
||||||
/> -->
|
/> -->
|
||||||
<el-option v-for="item of dict.type.ReadingType" :key="item.value" :label="item.label"
|
<el-option
|
||||||
:value="item.value" />
|
v-for="item of dict.type.ReadingType"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="Expedited: ">
|
<el-form-item label="Expedited: ">
|
||||||
<el-select v-model="searchData.Expedited" value-key="value" clearable style="width: 100%">
|
<el-select
|
||||||
<el-option v-for="item in expeditedOption" :key="item.value" :label="item.label" :value="item.value" />
|
v-model="searchData.Expedited"
|
||||||
|
value-key="value"
|
||||||
|
clearable
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item in expeditedOption"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="BeginDate: ">
|
<el-form-item label="BeginDate: ">
|
||||||
<el-date-picker v-model="searchData.BeginDate" value-format="yyyy-MM-dd" format="yyyy-MM-dd" type="date"
|
<el-date-picker
|
||||||
:picker-options="beginPickerOption" :clearable="false" style="width: 100%" />
|
v-model="searchData.BeginDate"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
type="date"
|
||||||
|
:picker-options="beginPickerOption"
|
||||||
|
:clearable="false"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="EndDate: ">
|
<el-form-item label="EndDate: ">
|
||||||
<el-date-picker v-model="searchData.EndDate" value-format="yyyy-MM-dd" format="yyyy-MM-dd" type="date"
|
<el-date-picker
|
||||||
:picker-options="endpickerOption" :clearable="false" style="width: 100%" />
|
v-model="searchData.EndDate"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
type="date"
|
||||||
|
:picker-options="endpickerOption"
|
||||||
|
:clearable="false"
|
||||||
|
style="width: 100%"
|
||||||
|
/>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-form-item label="Attended Reviewer Type:">
|
<el-form-item label="Attended Reviewer Type:">
|
||||||
<el-select v-model="searchData.AttendedReviewerType" placeholder="Attended Reviewer Type"
|
<el-select
|
||||||
style="width: 100%" clearable>
|
v-model="searchData.AttendedReviewerType"
|
||||||
<el-option v-for="item of $d.AttendedReviewerType" :key="item.value" :label="item.label"
|
placeholder="Attended Reviewer Type"
|
||||||
:value="item.value" />
|
style="width: 100%"
|
||||||
|
clearable
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.AttendedReviewerType"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<el-button type="primary" @click="handleSelectSearch">Search</el-button>
|
<el-button type="primary" @click="handleSelectSearch"
|
||||||
|
>Search</el-button
|
||||||
|
>
|
||||||
<el-button type="primary" @click="handleReset">Reset</el-button>
|
<el-button type="primary" @click="handleReset">Reset</el-button>
|
||||||
<el-button type="primary" @click="isShow = false">Back</el-button>
|
<el-button type="primary" @click="isShow = false">Back</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -153,89 +305,219 @@
|
||||||
|
|
||||||
<!-- 项目列表 -->
|
<!-- 项目列表 -->
|
||||||
<template slot="main-container">
|
<template slot="main-container">
|
||||||
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="listLoading" :data="list" stripe height="100"
|
<el-table
|
||||||
@selection-change="handleSelectChange" @sort-change="handleSortChange" @row-click="rowClick">
|
v-adaptive="{ bottomOffset: 60 }"
|
||||||
|
v-loading="listLoading"
|
||||||
|
:data="list"
|
||||||
|
stripe
|
||||||
|
height="100"
|
||||||
|
@selection-change="handleSelectChange"
|
||||||
|
@sort-change="handleSortChange"
|
||||||
|
@row-click="rowClick"
|
||||||
|
>
|
||||||
<el-table-column type="selection" align="left" width="45" />
|
<el-table-column type="selection" align="left" width="45" />
|
||||||
<el-table-column type="index" width="40" align="left" />
|
<el-table-column type="index" width="40" align="left" />
|
||||||
<el-table-column prop="TrialCode" :label="$t('trials:trials-list:table:trialId')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" width="120" />
|
prop="TrialCode"
|
||||||
<el-table-column prop="ResearchProgramNo" :label="$t('trials:trials-list:table:researchNumber')"
|
:label="$t('trials:trials-list:table:trialId')"
|
||||||
show-overflow-tooltip sortable="custom" min-width="160" />
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
width="120"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="ResearchProgramNo"
|
||||||
|
:label="$t('trials:trials-list:table:researchNumber')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-table-column prop="ExperimentName" :label="$t('trials:trials-list:table:experimentName')"
|
<el-table-column
|
||||||
show-overflow-tooltip sortable="custom" min-width="240" />
|
prop="ExperimentName"
|
||||||
<el-table-column prop="Sponsor" :label="$t('trials:trials-list:table:sponsor')" show-overflow-tooltip
|
:label="$t('trials:trials-list:table:experimentName')"
|
||||||
sortable="custom" min-width="120" />
|
show-overflow-tooltip
|
||||||
<el-table-column prop="TrialStatusStr" :label="$t('trials:trials-list:table:status')" show-overflow-tooltip
|
sortable="custom"
|
||||||
sortable="custom" min-width="120">
|
min-width="240"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="Sponsor"
|
||||||
|
:label="$t('trials:trials-list:table:sponsor')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="120"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="TrialStatusStr"
|
||||||
|
:label="$t('trials:trials-list:table:status')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="120"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.TrialStatusStr === 'Initializing'" type="info">{{ $fd('TrialStatusEnum',
|
<el-tag
|
||||||
scope.row.TrialStatusStr) }}</el-tag>
|
v-if="scope.row.TrialStatusStr === 'Initializing'"
|
||||||
<el-tag v-if="scope.row.TrialStatusStr === 'Ongoing'" type="primary">{{ $fd('TrialStatusEnum',
|
type="info"
|
||||||
scope.row.TrialStatusStr) }}</el-tag>
|
>{{ $fd('TrialStatusEnum', scope.row.TrialStatusStr) }}</el-tag
|
||||||
<el-tag v-if="scope.row.TrialStatusStr === 'Completed'" type="warning">{{ $fd('TrialStatusEnum',
|
>
|
||||||
scope.row.TrialStatusStr) }}</el-tag>
|
<el-tag
|
||||||
<el-tag v-if="scope.row.TrialStatusStr === 'Stopped'" type="danger">{{ $fd('TrialStatusEnum',
|
v-if="scope.row.TrialStatusStr === 'Ongoing'"
|
||||||
scope.row.TrialStatusStr) }}</el-tag>
|
type="primary"
|
||||||
|
>{{ $fd('TrialStatusEnum', scope.row.TrialStatusStr) }}</el-tag
|
||||||
|
>
|
||||||
|
<el-tag
|
||||||
|
v-if="scope.row.TrialStatusStr === 'Completed'"
|
||||||
|
type="warning"
|
||||||
|
>{{ $fd('TrialStatusEnum', scope.row.TrialStatusStr) }}</el-tag
|
||||||
|
>
|
||||||
|
<el-tag
|
||||||
|
v-if="scope.row.TrialStatusStr === 'Stopped'"
|
||||||
|
type="danger"
|
||||||
|
>{{ $fd('TrialStatusEnum', scope.row.TrialStatusStr) }}</el-tag
|
||||||
|
>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="hasPermi(['role:pm', 'role:apm'])" prop="ExpetiedTaskCount"
|
<el-table-column
|
||||||
:label="$t('trials:trials-list:table:ExpetiedTaskCount')" show-overflow-tooltip sortable="custom"
|
v-if="hasPermi(['role:pm', 'role:apm'])"
|
||||||
min-width="120" />
|
prop="ExpetiedTaskCount"
|
||||||
<el-table-column v-if="hasPermi(['role:pm', 'role:apm'])" prop="ReReadingApprovalCount"
|
:label="$t('trials:trials-list:table:ExpetiedTaskCount')"
|
||||||
:label="$t('trials:trials-list:table:ReReadingApprovalCount')" show-overflow-tooltip sortable="custom"
|
show-overflow-tooltip
|
||||||
min-width="180" />
|
sortable="custom"
|
||||||
<el-table-column v-if="hasPermi(['role:pm', 'role:apm'])" prop="PendingReconciliationCount"
|
min-width="120"
|
||||||
:label="$t('trials:trials-list:table:PendingReconciliationCount')" show-overflow-tooltip sortable="custom"
|
/>
|
||||||
min-width="140" />
|
<el-table-column
|
||||||
<el-table-column v-if="hasPermi(['role:pm', 'role:apm'])" prop="PendingResponseCount"
|
v-if="hasPermi(['role:pm', 'role:apm'])"
|
||||||
:label="$t('trials:trials-list:table:PendingResponseCount')" show-overflow-tooltip sortable="custom"
|
prop="ReReadingApprovalCount"
|
||||||
min-width="140" />
|
:label="$t('trials:trials-list:table:ReReadingApprovalCount')"
|
||||||
<el-table-column v-if="hasPermi(['role:crc', 'role:cra'])" prop="CRC_UrgentCount"
|
show-overflow-tooltip
|
||||||
:label="$t('trials:trials-list:table:CRC_UrgentCount')" show-overflow-tooltip sortable="custom"
|
sortable="custom"
|
||||||
min-width="160" />
|
min-width="180"
|
||||||
<el-table-column v-if="hasPermi(['role:crc', 'role:cra'])" prop="CRC_QCQuestionCount"
|
/>
|
||||||
:label="$t('trials:trials-list:table:CRC_QCQuestionCount')" show-overflow-tooltip sortable="custom"
|
<el-table-column
|
||||||
min-width="160" />
|
v-if="hasPermi(['role:pm', 'role:apm'])"
|
||||||
<el-table-column v-if="hasPermi(['role:crc', 'role:cra'])" prop="CRC_CheckQuestionCount"
|
prop="PendingReconciliationCount"
|
||||||
:label="$t('trials:trials-list:table:CRC_CheckQuestionCount')" show-overflow-tooltip sortable="custom"
|
:label="$t('trials:trials-list:table:PendingReconciliationCount')"
|
||||||
min-width="160" />
|
show-overflow-tooltip
|
||||||
<el-table-column v-if="hasPermi(['role:ir'])" prop="IR_ReadingCriterionList"
|
sortable="custom"
|
||||||
:label="$t('trials:trials-list:table:IR_ReadingCriterionList')" show-overflow-tooltip min-width="160">
|
min-width="140"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:pm', 'role:apm'])"
|
||||||
|
prop="PendingResponseCount"
|
||||||
|
:label="$t('trials:trials-list:table:PendingResponseCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="140"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:crc', 'role:cra'])"
|
||||||
|
prop="CRC_UrgentCount"
|
||||||
|
:label="$t('trials:trials-list:table:CRC_UrgentCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:crc', 'role:cra'])"
|
||||||
|
prop="CRC_QCQuestionCount"
|
||||||
|
:label="$t('trials:trials-list:table:CRC_QCQuestionCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:crc', 'role:cra'])"
|
||||||
|
prop="CRC_CheckQuestionCount"
|
||||||
|
:label="$t('trials:trials-list:table:CRC_CheckQuestionCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:ir'])"
|
||||||
|
prop="IR_ReadingCriterionList"
|
||||||
|
:label="$t('trials:trials-list:table:IR_ReadingCriterionList')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="160"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.IR_ReadingCriterionList.join(', ') }}
|
{{ scope.row.IR_ReadingCriterionList.join(', ') }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="hasPermi(['role:ir'])" prop="IR_UrgentCount"
|
<el-table-column
|
||||||
:label="$t('trials:trials-list:table:IR_UrgentCount')" show-overflow-tooltip sortable="custom"
|
v-if="hasPermi(['role:ir'])"
|
||||||
min-width="160" />
|
prop="IR_UrgentCount"
|
||||||
<el-table-column v-if="hasPermi(['role:ir'])" prop="IR_UnReadCount"
|
:label="$t('trials:trials-list:table:IR_UrgentCount')"
|
||||||
:label="$t('trials:trials-list:table:IR_UnReadCount')" show-overflow-tooltip sortable="custom"
|
show-overflow-tooltip
|
||||||
min-width="160" />
|
sortable="custom"
|
||||||
<el-table-column v-if="hasPermi(['role:ir'])" prop="IR_TotalReadCount"
|
min-width="160"
|
||||||
:label="$t('trials:trials-list:table:IR_TotalReadCount')" show-overflow-tooltip sortable="custom"
|
/>
|
||||||
min-width="170" />
|
<el-table-column
|
||||||
<el-table-column v-if="hasPermi(['role:ir'])" prop="IR_PMEmailList"
|
v-if="hasPermi(['role:ir'])"
|
||||||
:label="$t('trials:trials-list:table:IR_PMEmailList')" show-overflow-tooltip min-width="170">
|
prop="IR_UnReadCount"
|
||||||
|
:label="$t('trials:trials-list:table:IR_UnReadCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:ir'])"
|
||||||
|
prop="IR_TotalReadCount"
|
||||||
|
:label="$t('trials:trials-list:table:IR_TotalReadCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="170"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:ir'])"
|
||||||
|
prop="IR_PMEmailList"
|
||||||
|
:label="$t('trials:trials-list:table:IR_PMEmailList')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
min-width="170"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.row.IR_PMEmailList.join(', ') }}
|
{{ scope.row.IR_PMEmailList.join(', ') }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column v-if="hasPermi(['role:iqc'])" prop="IQC_UrgentCount"
|
<el-table-column
|
||||||
:label="$t('trials:trials-list:table:IQC_UrgentCount')" show-overflow-tooltip sortable="custom"
|
v-if="hasPermi(['role:iqc'])"
|
||||||
min-width="140" />
|
prop="IQC_UrgentCount"
|
||||||
<el-table-column v-if="hasPermi(['role:iqc'])" prop="IQC_ToBeClaimedCount"
|
:label="$t('trials:trials-list:table:IQC_UrgentCount')"
|
||||||
:label="$t('trials:trials-list:table:IQC_ToBeClaimedCount')" show-overflow-tooltip sortable="custom"
|
show-overflow-tooltip
|
||||||
min-width="140" />
|
sortable="custom"
|
||||||
<el-table-column v-if="hasPermi(['role:iqc'])" prop="IQC_AuditToBeDealedCount"
|
min-width="140"
|
||||||
:label="$t('trials:trials-list:table:IQC_AuditToBeDealedCount')" show-overflow-tooltip sortable="custom"
|
/>
|
||||||
min-width="140" />
|
<el-table-column
|
||||||
<el-table-column v-if="hasPermi(['role:iqc'])" prop="IQC_QuestionToBeDealedCount"
|
v-if="hasPermi(['role:iqc'])"
|
||||||
:label="$t('trials:trials-list:table:IQC_QuestionToBeDealedCount')" show-overflow-tooltip sortable="custom"
|
prop="IQC_ToBeClaimedCount"
|
||||||
min-width="160" />
|
:label="$t('trials:trials-list:table:IQC_ToBeClaimedCount')"
|
||||||
<el-table-column v-if="hasPermi(['role:mim'])" prop="MIM_UrgentCount"
|
show-overflow-tooltip
|
||||||
:label="$t('trials:trials-list:table:MIM_UrgentCount')" show-overflow-tooltip sortable="custom"
|
sortable="custom"
|
||||||
min-width="160" />
|
min-width="140"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:iqc'])"
|
||||||
|
prop="IQC_AuditToBeDealedCount"
|
||||||
|
:label="$t('trials:trials-list:table:IQC_AuditToBeDealedCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="140"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:iqc'])"
|
||||||
|
prop="IQC_QuestionToBeDealedCount"
|
||||||
|
:label="$t('trials:trials-list:table:IQC_QuestionToBeDealedCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:mim'])"
|
||||||
|
prop="MIM_UrgentCount"
|
||||||
|
:label="$t('trials:trials-list:table:MIM_UrgentCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
<!-- <el-table-column
|
<!-- <el-table-column
|
||||||
v-if="hasPermi(['role:mim'])"
|
v-if="hasPermi(['role:mim'])"
|
||||||
prop="MIM_UrgentCount"
|
prop="MIM_UrgentCount"
|
||||||
|
|
@ -244,63 +526,127 @@
|
||||||
sortable="custom"
|
sortable="custom"
|
||||||
min-width="160"
|
min-width="160"
|
||||||
/> -->
|
/> -->
|
||||||
<el-table-column v-if="hasPermi(['role:mim'])" prop="MIM_PendingReviewCount"
|
<el-table-column
|
||||||
:label="$t('trials:trials-list:table:MIM_PendingReviewCount')" show-overflow-tooltip sortable="custom"
|
v-if="hasPermi(['role:mim'])"
|
||||||
min-width="160" />
|
prop="MIM_PendingReviewCount"
|
||||||
<el-table-column v-if="hasPermi(['role:mim'])" prop="MIM_PendingResponseCount"
|
:label="$t('trials:trials-list:table:MIM_PendingReviewCount')"
|
||||||
:label="$t('trials:trials-list:table:MIM_PendingResponseCount')" show-overflow-tooltip sortable="custom"
|
show-overflow-tooltip
|
||||||
min-width="160" />
|
sortable="custom"
|
||||||
<el-table-column v-if="hasPermi(['role:spm', 'role:cpm'])" prop="SPM_ReReadingApprovalCount"
|
min-width="160"
|
||||||
:label="$t('trials:trials-list:table:SPM_ReReadingApprovalCount')" show-overflow-tooltip sortable="custom"
|
/>
|
||||||
min-width="160" />
|
<el-table-column
|
||||||
<el-table-column v-if="hasPermi(['role:spm', 'role:cpm'])" prop="SPM_ReviewerSelectApprovalCount" :label="$t('trials:trials-list:table:SPM_ReviewerSelectApprovalCount')
|
v-if="hasPermi(['role:mim'])"
|
||||||
" show-overflow-tooltip sortable="custom" min-width="160" />
|
prop="MIM_PendingResponseCount"
|
||||||
<el-table-column prop="CreateTime" :label="$t('trials:trials-list:table:createDate')" show-overflow-tooltip
|
:label="$t('trials:trials-list:table:MIM_PendingResponseCount')"
|
||||||
sortable="custom" width="180" />
|
show-overflow-tooltip
|
||||||
<el-table-column :label="$t('common:action:action')" width="260" align="left" fixed="right">
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:spm', 'role:cpm'])"
|
||||||
|
prop="SPM_ReReadingApprovalCount"
|
||||||
|
:label="$t('trials:trials-list:table:SPM_ReReadingApprovalCount')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
v-if="hasPermi(['role:spm', 'role:cpm'])"
|
||||||
|
prop="SPM_ReviewerSelectApprovalCount"
|
||||||
|
:label="
|
||||||
|
$t('trials:trials-list:table:SPM_ReviewerSelectApprovalCount')
|
||||||
|
"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
min-width="160"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
prop="CreateTime"
|
||||||
|
:label="$t('trials:trials-list:table:createDate')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
width="180"
|
||||||
|
/>
|
||||||
|
<el-table-column
|
||||||
|
:label="$t('common:action:action')"
|
||||||
|
width="260"
|
||||||
|
align="left"
|
||||||
|
fixed="right"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 详情 -->
|
<!-- 详情 -->
|
||||||
<el-button v-hasPermi="['trials:trials-list:panel']" circle icon="el-icon-info" :disabled="(scope.row.TrialStatusStr === 'Initializing' &&
|
<el-button
|
||||||
!hasPermi(['role:pm'])) ||
|
v-hasPermi="['trials:trials-list:panel']"
|
||||||
scope.row.IsDeleted ||
|
circle
|
||||||
((scope.row.TrialStatusStr === 'Completed' ||
|
icon="el-icon-info"
|
||||||
scope.row.TrialStatusStr === 'Stopped') &&
|
:disabled="
|
||||||
!(
|
(scope.row.TrialStatusStr === 'Initializing' &&
|
||||||
hasPermi(['role:qa']) ||
|
!hasPermi(['role:pm'])) ||
|
||||||
hasPermi(['role:ea']) ||
|
scope.row.IsDeleted ||
|
||||||
hasPermi(['role:pm']) ||
|
((scope.row.TrialStatusStr === 'Completed' ||
|
||||||
hasPermi(['role:op']) ||
|
scope.row.TrialStatusStr === 'Stopped') &&
|
||||||
hasPermi(['role:dev']) ||
|
!(
|
||||||
hasPermi(['role:admin'])
|
hasPermi(['role:qa']) ||
|
||||||
))
|
hasPermi(['role:ea']) ||
|
||||||
" :title="$t('trials:trials-list:action:panel')" @click.stop="handleDetail(scope.row)" />
|
hasPermi(['role:pm'])
|
||||||
|
))
|
||||||
|
"
|
||||||
|
:title="$t('trials:trials-list:action:panel')"
|
||||||
|
@click.stop="handleDetail(scope.row)"
|
||||||
|
/>
|
||||||
<!-- 编辑项目基本信息 -->
|
<!-- 编辑项目基本信息 -->
|
||||||
<el-button v-hasPermi="['trials:trials-list:edit']" circle icon="el-icon-edit-outline"
|
<el-button
|
||||||
:disabled="scope.row.IsDeleted" :title="$t('trials:trials-list:action:edit')"
|
v-hasPermi="['trials:trials-list:edit']"
|
||||||
@click.stop="handleEdit(scope.row)" />
|
circle
|
||||||
|
icon="el-icon-edit-outline"
|
||||||
|
:disabled="scope.row.IsDeleted"
|
||||||
|
:title="$t('trials:trials-list:action:edit')"
|
||||||
|
@click.stop="handleEdit(scope.row)"
|
||||||
|
/>
|
||||||
<!-- 修改项目状态 -->
|
<!-- 修改项目状态 -->
|
||||||
<el-button v-hasPermi="['trials:trials-list:status']" circle icon="el-icon-edit"
|
<el-button
|
||||||
:disabled="scope.row.IsDeleted" :title="$t('trials:trials-list:action:status')"
|
v-hasPermi="['trials:trials-list:status']"
|
||||||
@click.stop="handleStatus(scope.row)" />
|
circle
|
||||||
|
icon="el-icon-edit"
|
||||||
|
:disabled="scope.row.IsDeleted"
|
||||||
|
:title="$t('trials:trials-list:action:status')"
|
||||||
|
@click.stop="handleStatus(scope.row)"
|
||||||
|
/>
|
||||||
<!--项目文档-->
|
<!--项目文档-->
|
||||||
<el-button v-hasPermi="[
|
<el-button
|
||||||
'trials:trials-panel:trial-summary:trial-document:inspect',
|
v-hasPermi="[
|
||||||
'trials:trials-panel:trial-summary:trial-document:manage',
|
'trials:trials-panel:trial-summary:trial-document:inspect',
|
||||||
]" circle icon="el-icon-folder-opened" :disabled="(scope.row.TrialStatusStr === 'Initializing' &&
|
'trials:trials-panel:trial-summary:trial-document:manage',
|
||||||
!hasPermi(['role:pm'])) ||
|
]"
|
||||||
scope.row.IsDeleted ||
|
circle
|
||||||
((scope.row.TrialStatusStr === 'Completed' ||
|
icon="el-icon-folder-opened"
|
||||||
scope.row.TrialStatusStr === 'Stopped') &&
|
:disabled="
|
||||||
!(
|
(scope.row.TrialStatusStr === 'Initializing' &&
|
||||||
hasPermi(['role:qa']) ||
|
!hasPermi(['role:pm'])) ||
|
||||||
hasPermi(['role:ea']) ||
|
scope.row.IsDeleted ||
|
||||||
hasPermi(['role:pm'])
|
((scope.row.TrialStatusStr === 'Completed' ||
|
||||||
))
|
scope.row.TrialStatusStr === 'Stopped') &&
|
||||||
" :title="$t('trials:trials-list:action:trialDocument')" @click.stop="toTrialDocument(scope.row)" />
|
!(
|
||||||
|
hasPermi(['role:qa']) ||
|
||||||
|
hasPermi(['role:ea']) ||
|
||||||
|
hasPermi(['role:pm'])
|
||||||
|
))
|
||||||
|
"
|
||||||
|
:title="$t('trials:trials-list:action:trialDocument')"
|
||||||
|
@click.stop="toTrialDocument(scope.row)"
|
||||||
|
/>
|
||||||
<!-- 废除项目 -->
|
<!-- 废除项目 -->
|
||||||
<el-button v-hasPermi="['trials:trials-list:abolish']" circle icon="el-icon-delete" :disabled="scope.row.IsDeleted ||
|
<el-button
|
||||||
scope.row.TrialStatusStr !== 'Initializing'
|
v-hasPermi="['trials:trials-list:abolish']"
|
||||||
" :title="$t('trials:trials-list:action:abolition')" @click.stop="handleAbandon(scope.row)" />
|
circle
|
||||||
|
icon="el-icon-delete"
|
||||||
|
:disabled="
|
||||||
|
scope.row.IsDeleted ||
|
||||||
|
scope.row.TrialStatusStr !== 'Initializing'
|
||||||
|
"
|
||||||
|
:title="$t('trials:trials-list:action:abolition')"
|
||||||
|
@click.stop="handleAbandon(scope.row)"
|
||||||
|
/>
|
||||||
<!-- 代办详情-->
|
<!-- 代办详情-->
|
||||||
<!-- <el-button-->
|
<!-- <el-button-->
|
||||||
<!-- v-hasPermi="['trials:trials-list:abolish']"-->
|
<!-- v-hasPermi="['trials:trials-list:abolish']"-->
|
||||||
|
|
@ -315,26 +661,61 @@
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页组件 -->
|
<!-- 分页组件 -->
|
||||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination
|
||||||
@pagination="getList" />
|
class="page"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="searchData.PageIndex"
|
||||||
|
:limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 新增/编辑项目 -->
|
<!-- 新增/编辑项目 -->
|
||||||
<el-dialog v-if="dialogVisible" :visible.sync="dialogVisible" :title="title" :fullscreen="true" append-to-body
|
<el-dialog
|
||||||
custom-class="base-dialog-wrapper">
|
v-if="dialogVisible"
|
||||||
<TrialForm :trial-id="currentId" @getList="getList" @closeDialog="closeDialog" />
|
:visible.sync="dialogVisible"
|
||||||
|
:title="title"
|
||||||
|
:fullscreen="true"
|
||||||
|
append-to-body
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
|
<TrialForm
|
||||||
|
:trial-id="currentId"
|
||||||
|
@getList="getList"
|
||||||
|
@closeDialog="closeDialog"
|
||||||
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 修改项目状态 -->
|
<!-- 修改项目状态 -->
|
||||||
<el-dialog v-if="statusVisible" :visible.sync="statusVisible" :close-on-click-modal="false"
|
<el-dialog
|
||||||
:title="$t('trials:trials-list:dialogTitle:changeStatus')" width="700px" custom-class="base-dialog-wrapper"
|
v-if="statusVisible"
|
||||||
append-to-body>
|
:visible.sync="statusVisible"
|
||||||
<TrialStatusForm :data="currentRow" @closeDialog="closeStatusDialog" @getList="getList" />
|
:close-on-click-modal="false"
|
||||||
|
:title="$t('trials:trials-list:dialogTitle:changeStatus')"
|
||||||
|
width="700px"
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
|
<TrialStatusForm
|
||||||
|
:data="currentRow"
|
||||||
|
@closeDialog="closeStatusDialog"
|
||||||
|
@getList="getList"
|
||||||
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<el-dialog v-if="doneDialogVisible" :visible.sync="doneDialogVisible" :title="doneTitle" :fullscreen="true"
|
<el-dialog
|
||||||
append-to-body custom-class="base-dialog-wrapper">
|
v-if="doneDialogVisible"
|
||||||
<DoneList :trial-id="currentId" @getList="getList" @closeDialog="doneDialogVisible = false" />
|
:visible.sync="doneDialogVisible"
|
||||||
|
:title="doneTitle"
|
||||||
|
:fullscreen="true"
|
||||||
|
append-to-body
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
|
<DoneList
|
||||||
|
:trial-id="currentId"
|
||||||
|
@getList="getList"
|
||||||
|
@closeDialog="doneDialogVisible = false"
|
||||||
|
/>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</BaseContainer>
|
</BaseContainer>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -516,7 +897,7 @@ export default {
|
||||||
this.$confirm(res.ErrorMessage, {
|
this.$confirm(res.ErrorMessage, {
|
||||||
type: 'warning',
|
type: 'warning',
|
||||||
showCancelButton: false,
|
showCancelButton: false,
|
||||||
callback: (action) => { },
|
callback: (action) => {},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -541,7 +922,7 @@ export default {
|
||||||
this.currentRow = { ...row }
|
this.currentRow = { ...row }
|
||||||
this.abandonTrial()
|
this.abandonTrial()
|
||||||
})
|
})
|
||||||
.catch(() => { })
|
.catch(() => {})
|
||||||
},
|
},
|
||||||
// 废除项目
|
// 废除项目
|
||||||
abandonTrial() {
|
abandonTrial() {
|
||||||
|
|
@ -573,10 +954,7 @@ export default {
|
||||||
!(
|
!(
|
||||||
this.hasPermi(['role:qa']) ||
|
this.hasPermi(['role:qa']) ||
|
||||||
this.hasPermi(['role:ea']) ||
|
this.hasPermi(['role:ea']) ||
|
||||||
this.hasPermi(['role:pm']) ||
|
this.hasPermi(['role:pm'])
|
||||||
hasPermi(['role:op']) ||
|
|
||||||
hasPermi(['role:dev']) ||
|
|
||||||
hasPermi(['role:admin'])
|
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -4,108 +4,158 @@
|
||||||
<div class="title" v-if="isDoc">
|
<div class="title" v-if="isDoc">
|
||||||
{{ TITLE }}
|
{{ TITLE }}
|
||||||
</div>
|
</div>
|
||||||
<el-row v-if="isSystem" style="width: 100%;">
|
|
||||||
<el-col :span="12">
|
|
||||||
<h3>{{ TITLE }}</h3>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12" style="text-align:right;">
|
|
||||||
<h3>
|
|
||||||
<Pagination class="page" :total="total" :page.sync="searchData.pageIndex" :limit.sync="searchData.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>
|
|
||||||
</template>
|
</template>
|
||||||
<!-- 搜索框 -->
|
<!-- 搜索框 -->
|
||||||
<template slot="search-container">
|
<template slot="search-container">
|
||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<!-- 文件类型 -->
|
<!-- 文件类型 -->
|
||||||
<el-form-item :label="$t('trials:signRecords:table:fileType')">
|
<el-form-item :label="$t('trials:signRecords:table:fileType')">
|
||||||
<el-select v-model="searchData.FileTypeId" clearable style="width: 150px">
|
<el-select
|
||||||
<template v-if="isSystem">
|
v-model="searchData.FileTypeId"
|
||||||
<el-option v-for="item of typeOptions" :key="item.id" :label="item.label" :value="item.id" />
|
clearable
|
||||||
</template>
|
style="width: 150px"
|
||||||
<template v-else>
|
>
|
||||||
<el-option v-for="item of typeOptions" :key="item.FileTypeId" :label="item.FileType"
|
<el-option
|
||||||
:value="item.FileTypeId" />
|
v-for="item of typeOptions"
|
||||||
</template>
|
:key="item.FileTypeId"
|
||||||
|
:label="item.FileType"
|
||||||
|
:value="item.FileTypeId"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 文件名称 -->
|
<!-- 文件名称 -->
|
||||||
<el-form-item :label="$t('trials:signRecords:table:fileName')">
|
<el-form-item :label="$t('trials:signRecords:table:fileName')">
|
||||||
<el-input v-model="searchData.Name" clearable style="width: 120px" />
|
<el-input v-model="searchData.Name" style="width: 120px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 签署人 -->
|
<!-- 签署人 -->
|
||||||
<el-form-item :label="$t('trials:signRecords:table:user')" v-if="!isDoc">
|
<el-form-item
|
||||||
<el-select v-model="searchData.UserId" clearable filterable style="width: 140px">
|
:label="$t('trials:signRecords:table:user')"
|
||||||
<el-option v-for="item of userOptions" :key="item.ConfirmUserId" :label="item.FullName"
|
v-if="!isDoc"
|
||||||
:value="item.ConfirmUserId">
|
>
|
||||||
<span style="float: left">{{ item.RealName || item.FullName }}</span>
|
<el-select
|
||||||
<span style="
|
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"
|
||||||
|
>
|
||||||
|
<span style="float: left">{{ item.RealName }}</span>
|
||||||
|
<span
|
||||||
|
style="
|
||||||
float: right;
|
float: right;
|
||||||
color: #8492a6;
|
color: #8492a6;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
margin-left: 5px;
|
margin-left: 5px;
|
||||||
">
|
"
|
||||||
|
>
|
||||||
{{ item.UserName }}
|
{{ item.UserName }}
|
||||||
</span>
|
</span>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 用户名 -->
|
|
||||||
<el-form-item :label="$t('trials:signRecords:table:userName')" v-if="isSystem">
|
|
||||||
<el-input v-model="searchData.userName" clearable style="width: 120px" />
|
|
||||||
</el-form-item>
|
|
||||||
<!-- 用户类型 -->
|
<!-- 用户类型 -->
|
||||||
<el-form-item :label="$t('trials:signRecords:table:userType')" v-if="!isDoc">
|
<el-form-item
|
||||||
<el-select v-model="searchData.UserTypeId" clearable filterable style="width: 120px">
|
:label="$t('trials:signRecords:table:userType')"
|
||||||
<el-option v-for="item of userTypeOptions" v-show="item.UserTypeEnum !== 26 && item.UserTypeEnum !== 27"
|
v-if="!isDoc"
|
||||||
:key="item.Id" :label="item.UserTypeShortName" :value="item.Id">
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.UserTypeId"
|
||||||
|
clearable
|
||||||
|
filterable
|
||||||
|
style="width: 120px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of userTypeOptions"
|
||||||
|
v-show="item.UserTypeEnum !== 26 && item.UserTypeEnum !== 27"
|
||||||
|
:key="item.Id"
|
||||||
|
:label="item.UserTypeShortName"
|
||||||
|
:value="item.Id"
|
||||||
|
>
|
||||||
<span>{{ item.UserType }}</span>
|
<span>{{ item.UserType }}</span>
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:signRecords:table:isSign')" v-if="!isDoc || !viewStatus">
|
<el-form-item
|
||||||
<el-select v-model="searchData.IsConfirmed" clearable style="width: 120px">
|
:label="$t('trials:signRecords:table:isSign')"
|
||||||
<el-option v-for="i of $d.TrainingStatusEnum" :key="'IsConfirmed' + i.label" :value="i.value"
|
v-if="!isDoc || !viewStatus"
|
||||||
:label="i.label" />
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.IsConfirmed"
|
||||||
|
clearable
|
||||||
|
style="width: 120px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="i of $d.TrainingStatusEnum"
|
||||||
|
:key="'IsConfirmed' + i.label"
|
||||||
|
:value="i.value"
|
||||||
|
:label="i.label"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="isDoc
|
<el-form-item
|
||||||
? $t('trials:signRecords:table:isDeletedFile')
|
:label="
|
||||||
: $t('trials:signRecords:table:isDeleted')
|
isDoc
|
||||||
">
|
? $t('trials:signRecords:table:isDeletedFile')
|
||||||
<el-select v-model="searchData.IsDeleted" clearable style="width: 120px">
|
: $t('trials:signRecords:table:isDeleted')
|
||||||
<el-option v-for="i of $d.TrainingStatus" :key="'IsDeleted' + i.label" :value="i.value" :label="i.label" />
|
"
|
||||||
|
>
|
||||||
|
<el-select
|
||||||
|
v-model="searchData.IsDeleted"
|
||||||
|
clearable
|
||||||
|
style="width: 120px"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="i of $d.TrainingStatus"
|
||||||
|
:key="'IsDeleted' + i.label"
|
||||||
|
:value="i.value"
|
||||||
|
:label="i.label"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:signRecords:table:username')" v-if="isDoc">
|
<el-form-item
|
||||||
|
:label="$t('trials:signRecords:table:username')"
|
||||||
|
v-if="isDoc"
|
||||||
|
>
|
||||||
<el-input v-model="searchData.UserName" style="width: 120px" />
|
<el-input v-model="searchData.UserName" style="width: 120px" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:signRecords:table:confirmTime')" v-if="isDoc || isSystem">
|
<el-form-item
|
||||||
<el-date-picker v-model="timeList" @change="changeTimeList" value-format="yyyy-MM-dd HH:mm:ss"
|
:label="$t('trials:signRecords:table:confirmTime')"
|
||||||
:default-time="['00:00:00', '23:59:59']" type="datetimerange">
|
v-if="isDoc"
|
||||||
|
>
|
||||||
|
<el-date-picker
|
||||||
|
v-model="timeList"
|
||||||
|
@change="changeTimeList"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
type="datetimerange"
|
||||||
|
>
|
||||||
</el-date-picker>
|
</el-date-picker>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item :label="$t('trials:signRecords:table:uploadTime')" v-if="isSystem">
|
|
||||||
<el-date-picker v-model="timeListC" value-format="yyyy-MM-dd HH:mm:ss" format="yyyy-MM-dd HH:mm:ss"
|
|
||||||
type="datetimerange" :default-time="['00:00:00', '23:59:59']" @change="changeTimeListC" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
<!-- 查询 -->
|
<!-- 查询 -->
|
||||||
<el-button icon="el-icon-search" type="primary" @click="handleSearch">
|
<el-button icon="el-icon-search" type="primary" @click="handleSearch">
|
||||||
{{ $t('common:button:search') }}
|
{{ $t('common:button:search') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 重置 -->
|
<!-- 重置 -->
|
||||||
<el-button icon="el-icon-refresh-left" type="primary" @click="handleReset">
|
<el-button
|
||||||
|
icon="el-icon-refresh-left"
|
||||||
|
type="primary"
|
||||||
|
@click="handleReset"
|
||||||
|
>
|
||||||
{{ $t('common:button:reset') }}
|
{{ $t('common:button:reset') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 导出 -->
|
<!-- 导出 -->
|
||||||
<el-button type="primary" icon="el-icon-download" :loading="exportLoading" @click="handleExport"
|
<el-button
|
||||||
v-if="!isSystem || !hasPermi(['role:ea'])">
|
type="primary"
|
||||||
|
icon="el-icon-download"
|
||||||
|
:loading="exportLoading"
|
||||||
|
@click="handleExport"
|
||||||
|
>
|
||||||
{{ $t('common:button:export') }}
|
{{ $t('common:button:export') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -114,25 +164,39 @@
|
||||||
|
|
||||||
<template slot="main-container">
|
<template slot="main-container">
|
||||||
<!-- 系统文件列表 -->
|
<!-- 系统文件列表 -->
|
||||||
<el-table ref="AttachmentsManagement" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe
|
<el-table
|
||||||
height="100" @sort-change="handleSortByColumn">
|
ref="AttachmentsManagement"
|
||||||
|
v-loading="loading"
|
||||||
|
v-adaptive="{ bottomOffset: 60 }"
|
||||||
|
:data="list"
|
||||||
|
stripe
|
||||||
|
height="100"
|
||||||
|
@sort-change="handleSortByColumn"
|
||||||
|
>
|
||||||
<el-table-column type="index" width="40" />
|
<el-table-column type="index" width="40" />
|
||||||
<!-- 文件类型 -->
|
<!-- 文件类型 -->
|
||||||
<el-table-column prop="FileType" :label="$t('trials:signRecords:table:fileType')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" width="160" />
|
prop="FileType"
|
||||||
|
:label="$t('trials:signRecords:table:fileType')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
width="160"
|
||||||
|
/>
|
||||||
<!-- 文件名称 -->
|
<!-- 文件名称 -->
|
||||||
<el-table-column prop="Name" :label="$t('trials:signRecords:table:fileName')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
prop="Name"
|
||||||
<el-table-column :label="$t('trials:signRecords:table:AttachmentCount')" prop="AttachmentCount"
|
:label="$t('trials:signRecords:table:fileName')"
|
||||||
show-overflow-tooltip>
|
show-overflow-tooltip
|
||||||
<template slot-scope="scope">
|
sortable="custom"
|
||||||
<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
|
<el-table-column
|
||||||
width="160" sortable="custom" v-if="!isSystem">
|
prop="IsSystemDoc"
|
||||||
|
:label="$t('trials:signRecords:table:fileLevel')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
width="160"
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsSystemDoc" type="primary">{{
|
<el-tag v-if="scope.row.IsSystemDoc" type="primary">{{
|
||||||
$fd('IsSystemDoc', scope.row.IsSystemDoc)
|
$fd('IsSystemDoc', scope.row.IsSystemDoc)
|
||||||
|
|
@ -143,10 +207,16 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 是否废除 -->
|
<!-- 是否废除 -->
|
||||||
<el-table-column prop="IsDeleted" :label="isDoc
|
<el-table-column
|
||||||
? $t('trials:signRecords:table:isDeletedFile')
|
prop="IsDeleted"
|
||||||
: $t('trials:signRecords:table:isDeleted')
|
:label="
|
||||||
" show-overflow-tooltip sortable="custom">
|
isDoc
|
||||||
|
? $t('trials:signRecords:table:isDeletedFile')
|
||||||
|
: $t('trials:signRecords:table:isDeleted')
|
||||||
|
"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
|
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
|
||||||
$fd('TrainingStatus', scope.row.IsDeleted)
|
$fd('TrainingStatus', scope.row.IsDeleted)
|
||||||
|
|
@ -157,11 +227,20 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 上传时间 -->
|
<!-- 上传时间 -->
|
||||||
<el-table-column prop="CreateTime" :label="$t('trials:signRecords:table:uploadTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
width="160" sortable="custom" />
|
prop="CreateTime"
|
||||||
|
:label="$t('trials:signRecords:table:uploadTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
width="160"
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<!-- 是否签署 -->
|
<!-- 是否签署 -->
|
||||||
<el-table-column prop="ConfirmTime" :label="$t('trials:signRecords:table:isSign')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom">
|
prop="ConfirmTime"
|
||||||
|
:label="$t('trials:signRecords:table:isSign')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{
|
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{
|
||||||
$fd('TrainingStatusEnum', scope.row.IsConfirmed)
|
$fd('TrainingStatusEnum', scope.row.IsConfirmed)
|
||||||
|
|
@ -172,55 +251,86 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 签署人 -->
|
<!-- 签署人 -->
|
||||||
<el-table-column prop="RealName" :label="$t('trials:signRecords:table:user')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" v-if="!isDoc || !viewStatus" />
|
prop="RealName"
|
||||||
|
:label="$t('trials:signRecords:table:user')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
v-if="!isDoc || !viewStatus"
|
||||||
|
/>
|
||||||
<!-- 用户名 -->
|
<!-- 用户名 -->
|
||||||
<el-table-column prop="UserName" :label="$t('trials:signRecords:table:userName')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
prop="UserName"
|
||||||
|
:label="$t('trials:signRecords:table:userName')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<!-- 用户类型 -->
|
<!-- 用户类型 -->
|
||||||
<el-table-column prop="UserConfirmedUserTypeList" :label="$t('trials:signRecords:table:userType')"
|
<el-table-column
|
||||||
show-overflow-tooltip>
|
prop="UserConfirmedUserTypeList"
|
||||||
|
:label="$t('trials:signRecords:table:userType')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<span>{{
|
<span>{{
|
||||||
Array.isArray(scope.row.UserConfirmedUserTypeList) &&
|
Array.isArray(scope.row.UserConfirmedUserTypeList) &&
|
||||||
scope.row.UserConfirmedUserTypeList.length > 0
|
scope.row.UserConfirmedUserTypeList.length > 0
|
||||||
? scope.row.UserConfirmedUserTypeList.join(', ')
|
? scope.row.UserConfirmedUserTypeList.join(', ')
|
||||||
: ''
|
: ''
|
||||||
}}</span>
|
}}</span>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 签署时间 -->
|
<!-- 签署时间 -->
|
||||||
<el-table-column prop="ConfirmTime" :label="$t('trials:signRecords:table:confirmTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
prop="ConfirmTime"
|
||||||
|
:label="$t('trials:signRecords:table:confirmTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
<el-table-column :label="$t('common:action:action')">
|
<el-table-column :label="$t('common:action:action')">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 预览 -->
|
<!-- 预览 -->
|
||||||
<el-button circle :title="$t('trials:signRecords:action:preview')" icon="el-icon-view"
|
<el-button
|
||||||
@click="handlePreview(scope.row)" />
|
circle
|
||||||
|
:title="$t('trials:signRecords:action:preview')"
|
||||||
|
icon="el-icon-view"
|
||||||
|
@click="handlePreview(scope.row)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页组件 -->
|
<!-- 分页组件 -->
|
||||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination
|
||||||
@pagination="getList" v-if="!isSystem" />
|
class="page"
|
||||||
|
:total="total"
|
||||||
|
:page.sync="searchData.PageIndex"
|
||||||
|
:limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 预览文件 -->
|
<!-- 预览文件 -->
|
||||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="$t('trials:signRecords:action:preview')"
|
<el-dialog
|
||||||
:fullscreen="true" append-to-body custom-class="base-dialog-wrapper">
|
v-if="previewVisible"
|
||||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
:visible.sync="previewVisible"
|
||||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
:title="$t('trials:signRecords:action:preview')"
|
||||||
$t('trials:signRecords:table:AttachmentCount') }} ({{
|
:fullscreen="true"
|
||||||
currentRow.AttachmentCount }})</span>
|
append-to-body
|
||||||
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
|
custom-class="base-dialog-wrapper"
|
||||||
<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>
|
</div>
|
||||||
</el-dialog>
|
</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>
|
</BaseContainer>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -229,23 +339,16 @@ import {
|
||||||
getTrialUserSelect,
|
getTrialUserSelect,
|
||||||
getTrialUserTypeList,
|
getTrialUserTypeList,
|
||||||
getTrialDocAndSystemDocType,
|
getTrialDocAndSystemDocType,
|
||||||
getSysDocumentConfirmList,
|
|
||||||
getSysDocSignUserList
|
|
||||||
} from '@/api/trials'
|
} from '@/api/trials'
|
||||||
import { pMTrainingRecordList_Export, getSysDocumentConfirmList_Export } from '@/api/export'
|
import { pMTrainingRecordList_Export } from '@/api/export'
|
||||||
import BaseContainer from '@/components/BaseContainer'
|
import BaseContainer from '@/components/BaseContainer'
|
||||||
import Pagination from '@/components/Pagination'
|
import Pagination from '@/components/Pagination'
|
||||||
import PreviewFile from '@/components/PreviewFile/index'
|
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 = () => {
|
const searchDataDefault = () => {
|
||||||
return {
|
return {
|
||||||
UserName: null,
|
UserName: null,
|
||||||
StartConfirmTime: null,
|
StartConfirmTime: null,
|
||||||
EndConfirmTime: null,
|
EndConfirmTime: null,
|
||||||
EndCreateTime: null,
|
|
||||||
BeginCreateTime: null,
|
|
||||||
userName: null,
|
|
||||||
FileTypeId: '',
|
FileTypeId: '',
|
||||||
Name: '',
|
Name: '',
|
||||||
UserId: '',
|
UserId: '',
|
||||||
|
|
@ -258,7 +361,7 @@ const searchDataDefault = () => {
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
name: 'AttachmentsManagement',
|
name: 'AttachmentsManagement',
|
||||||
components: { BaseContainer, Pagination, PreviewFile, attachmentPreview, attachmentList },
|
components: { BaseContainer, Pagination, PreviewFile },
|
||||||
props: {
|
props: {
|
||||||
isDoc: {
|
isDoc: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
|
|
@ -272,10 +375,6 @@ export default {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
isSystem: {
|
|
||||||
type: Boolean,
|
|
||||||
default: false,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -294,14 +393,6 @@ export default {
|
||||||
trialId: this.$route.query.trialId,
|
trialId: this.$route.query.trialId,
|
||||||
exportLoading: false,
|
exportLoading: false,
|
||||||
timeList: [],
|
timeList: [],
|
||||||
timeListC: [],
|
|
||||||
SystemDocumentId: null,
|
|
||||||
perview_visible: null,
|
|
||||||
config: {
|
|
||||||
visible: false,
|
|
||||||
title: this.$t('dictionary:signature:attachmentList:title'),
|
|
||||||
width: '800px',
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -310,16 +401,6 @@ export default {
|
||||||
this.getUserType()
|
this.getUserType()
|
||||||
},
|
},
|
||||||
methods: {
|
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() {
|
changeTimeList() {
|
||||||
if (this.timeList) {
|
if (this.timeList) {
|
||||||
this.searchData.StartConfirmTime = this.timeList[0]
|
this.searchData.StartConfirmTime = this.timeList[0]
|
||||||
|
|
@ -329,26 +410,8 @@ export default {
|
||||||
this.searchData.EndConfirmTime = null
|
this.searchData.EndConfirmTime = null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
changeTimeListC() {
|
|
||||||
if (this.timeListC) {
|
|
||||||
this.searchData.BeginCreateTime = this.timeListC[0]
|
|
||||||
this.searchData.EndCreateTime = this.timeListC[1]
|
|
||||||
} else {
|
|
||||||
this.searchData.BeginCreateTime = null
|
|
||||||
this.searchData.EndCreateTime = null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleExport() {
|
handleExport() {
|
||||||
this.exportLoading = true
|
this.exportLoading = true
|
||||||
if (this.isSystem) {
|
|
||||||
return getSysDocumentConfirmList_Export(this.searchData)
|
|
||||||
.then(() => {
|
|
||||||
this.exportLoading = false
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
this.exportLoading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
pMTrainingRecordList_Export(this.searchData)
|
pMTrainingRecordList_Export(this.searchData)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
this.exportLoading = false
|
this.exportLoading = false
|
||||||
|
|
@ -369,52 +432,29 @@ export default {
|
||||||
this.searchData.UserTypeId = IR.Id
|
this.searchData.UserTypeId = IR.Id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.isSystem) {
|
this.searchData.TrialId = this.trialId
|
||||||
getSysDocumentConfirmList(this.searchData)
|
getDocumentConfirmList(this.searchData)
|
||||||
.then(async (res) => {
|
.then(async (res) => {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.list = res.Result.CurrentPageData
|
this.list = res.Result.CurrentPageData
|
||||||
this.total = res.Result.TotalCount
|
this.total = res.Result.TotalCount
|
||||||
})
|
console.log(this.total)
|
||||||
.catch(() => {
|
})
|
||||||
this.loading = false
|
.catch(() => {
|
||||||
})
|
this.loading = false
|
||||||
} else {
|
})
|
||||||
this.searchData.TrialId = this.trialId
|
|
||||||
getDocumentConfirmList(this.searchData)
|
|
||||||
.then(async (res) => {
|
|
||||||
this.loading = false
|
|
||||||
this.list = res.Result.CurrentPageData
|
|
||||||
this.total = res.Result.TotalCount
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
this.loading = false
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
// 获取文件类型下拉数据
|
// 获取文件类型下拉数据
|
||||||
getTypeOptions() {
|
getTypeOptions() {
|
||||||
if (this.isSystem) {
|
getTrialDocAndSystemDocType(this.trialId).then((res) => {
|
||||||
this.typeOptions = this.$d.Sys_Document
|
this.typeOptions = res.Result
|
||||||
} else {
|
})
|
||||||
getTrialDocAndSystemDocType(this.trialId).then((res) => {
|
|
||||||
this.typeOptions = res.Result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
},
|
},
|
||||||
// 获取当前项目下参与者信息
|
// 获取当前项目下参与者信息
|
||||||
getUserSelect() {
|
getUserSelect() {
|
||||||
if (this.isSystem) {
|
getTrialUserSelect(this.trialId).then((res) => {
|
||||||
getSysDocSignUserList().then((res) => {
|
this.userOptions = res.Result
|
||||||
this.userOptions = res.Result
|
})
|
||||||
})
|
|
||||||
} else {
|
|
||||||
getTrialUserSelect(this.trialId).then((res) => {
|
|
||||||
this.userOptions = res.Result
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
// 获取用户类型下拉数据
|
// 获取用户类型下拉数据
|
||||||
getUserType() {
|
getUserType() {
|
||||||
|
|
@ -441,7 +481,6 @@ export default {
|
||||||
handleReset() {
|
handleReset() {
|
||||||
this.searchData = searchDataDefault()
|
this.searchData = searchDataDefault()
|
||||||
this.timeList = []
|
this.timeList = []
|
||||||
this.timeListC = []
|
|
||||||
this.getList()
|
this.getList()
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.AttachmentsManagement.clearSort()
|
this.$refs.AttachmentsManagement.clearSort()
|
||||||
|
|
|
||||||
|
|
@ -5,9 +5,17 @@
|
||||||
<el-form :inline="true">
|
<el-form :inline="true">
|
||||||
<!-- 文件类型 -->
|
<!-- 文件类型 -->
|
||||||
<el-form-item :label="$t('trials:self-attachment:table:fileType')">
|
<el-form-item :label="$t('trials:self-attachment:table:fileType')">
|
||||||
<el-select v-model="searchData.FileTypeId" clearable style="width:150px;">
|
<el-select
|
||||||
<el-option v-for="item of typeOptions" :key="item.FileTypeId" :label="item.FileType"
|
v-model="searchData.FileTypeId"
|
||||||
:value="item.FileTypeId" />
|
clearable
|
||||||
|
style="width:150px;"
|
||||||
|
>
|
||||||
|
<el-option
|
||||||
|
v-for="item of typeOptions"
|
||||||
|
:key="item.FileTypeId"
|
||||||
|
:label="item.FileType"
|
||||||
|
:value="item.FileTypeId"
|
||||||
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 文件名称 -->
|
<!-- 文件名称 -->
|
||||||
|
|
@ -18,7 +26,7 @@
|
||||||
<el-form-item :label="$t('trials:self-attachment:table:isSign')">
|
<el-form-item :label="$t('trials:self-attachment:table:isSign')">
|
||||||
<el-select v-model="searchData.IsSign" clearable style="width:120px;">
|
<el-select v-model="searchData.IsSign" clearable style="width:120px;">
|
||||||
<template v-for="item of $d.TrainingStatusEnum">
|
<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>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
@ -36,71 +44,104 @@
|
||||||
</template>
|
</template>
|
||||||
<template slot="main-container">
|
<template slot="main-container">
|
||||||
<!-- 系统文件列表 -->
|
<!-- 系统文件列表 -->
|
||||||
<el-table ref="TrialAttachments" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe
|
<el-table
|
||||||
height="100" @sort-change="handleSortByColumn">
|
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="selection" width="50" />
|
||||||
<el-table-column type="index" width="40" />
|
<el-table-column type="index" width="40" />
|
||||||
<!-- 文件类型 -->
|
<!-- 文件类型 -->
|
||||||
<el-table-column prop="FileType" :label="$t('trials:self-attachment:table:fileType')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
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
|
<el-table-column
|
||||||
sortable="custom" />
|
prop="Name"
|
||||||
<el-table-column :label="$t('trials:self-attachment:table:AttachmentCount')" prop="AttachmentCount"
|
:label="$t('trials:self-attachment:table:fileName')"
|
||||||
show-overflow-tooltip sortable="custom">
|
show-overflow-tooltip
|
||||||
<template slot-scope="scope">
|
sortable="custom"
|
||||||
<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
|
<el-table-column
|
||||||
sortable="custom">
|
prop="IsDeleted"
|
||||||
|
:label="$t('trials:self-attachment:table:isDeleted')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{ $fd('TrainingStatus', scope.row.IsDeleted) }}</el-tag>
|
<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>
|
<el-tag v-else type="primary">{{ $fd('TrainingStatus', scope.row.IsDeleted) }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 上传时间 -->
|
<!-- 上传时间 -->
|
||||||
<el-table-column prop="CreateTime" :label="$t('trials:self-attachment:table:uploadTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
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
|
<el-table-column
|
||||||
sortable="custom">
|
prop="ConfirmTime"
|
||||||
|
:label="$t('trials:self-attachment:table:isSign')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
>
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed)
|
<el-tag v-if="scope.row.IsConfirmed" type="primary">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed) }}</el-tag>
|
||||||
}}</el-tag>
|
|
||||||
<el-tag v-else type="danger">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed) }}</el-tag>
|
<el-tag v-else type="danger">{{ $fd('TrainingStatusEnum', scope.row.IsConfirmed) }}</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 签署时间 -->
|
<!-- 签署时间 -->
|
||||||
<el-table-column prop="ConfirmTime" :label="$t('trials:self-attachment:table:signTime')" show-overflow-tooltip
|
<el-table-column
|
||||||
sortable="custom" />
|
prop="ConfirmTime"
|
||||||
|
:label="$t('trials:self-attachment:table:signTime')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
sortable="custom"
|
||||||
|
/>
|
||||||
|
|
||||||
<el-table-column :label="$t('common:action:action')">
|
<el-table-column :label="$t('common:action:action')">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 预览 -->
|
<!-- 预览 -->
|
||||||
<el-button icon="el-icon-view" circle :title="$t('trials:self-attachment:action:preview')"
|
<el-button
|
||||||
@click="handlePreview(scope.row)" />
|
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"
|
<el-button
|
||||||
:title="$t('trials:self-attachment:action:sign')" @click="handleSign(scope.row)" />
|
icon="el-icon-edit-outline"
|
||||||
|
circle
|
||||||
|
:disabled="!!scope.row.ConfirmTime"
|
||||||
|
:title="$t('trials:self-attachment:action:sign')"
|
||||||
|
@click="handleSign(scope.row)"
|
||||||
|
/>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
||||||
<!-- 分页组件 -->
|
<!-- 分页组件 -->
|
||||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||||
@pagination="getList" />
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<!-- 预览文件 -->
|
<!-- 预览文件 -->
|
||||||
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="title" :fullscreen="true" append-to-body
|
<el-dialog
|
||||||
custom-class="base-dialog-wrapper">
|
v-if="previewVisible"
|
||||||
<span style="position: fixed; left: 16px; top: 45px;cursor: pointer;font-size: 18px;color:#409EFF"
|
:visible.sync="previewVisible"
|
||||||
@click.stop="openAttachment(currentRow)" v-if="currentRow.AttachmentCount">{{
|
:title="title"
|
||||||
$t('trials:self-attachment:table:AttachmentCount') }} ({{
|
:fullscreen="true"
|
||||||
currentRow.AttachmentCount }})</span>
|
append-to-body
|
||||||
|
custom-class="base-dialog-wrapper"
|
||||||
|
>
|
||||||
<span v-if="!currentIsConfirm" style="position: fixed;right: 75px;top: 14px;">
|
<span v-if="!currentIsConfirm" style="position: fixed;right: 75px;top: 14px;">
|
||||||
<span style="color:red;margin-right:10px;">
|
<span style="color:red;margin-right:10px;">
|
||||||
<!-- 请仔细阅读文件,并签名确认 -->
|
<!-- 请仔细阅读文件,并签名确认 -->
|
||||||
|
|
@ -108,8 +149,13 @@
|
||||||
<span v-show="duration < currentMinMinutes * 60">{{ `(${currentMinMinutes * 60 - duration}s)` }}</span>
|
<span v-show="duration < currentMinMinutes * 60">{{ `(${currentMinMinutes * 60 - duration}s)` }}</span>
|
||||||
</span>
|
</span>
|
||||||
<!-- 签署 -->
|
<!-- 签署 -->
|
||||||
<el-button size="small" type="primary" :disabled="timer !== null || duration === 0" :loading="btnLoading"
|
<el-button
|
||||||
@click="handleConfirm">
|
size="small"
|
||||||
|
type="primary"
|
||||||
|
:disabled="timer !== null || duration === 0"
|
||||||
|
:loading="btnLoading"
|
||||||
|
@click="handleConfirm"
|
||||||
|
>
|
||||||
{{ $t('common:button:sign') }}
|
{{ $t('common:button:sign') }}
|
||||||
<!-- {{ duration >= currentMinMinutes * 60?'确认':`确认(${currentMinMinutes * 60 - duration}s)` }} -->
|
<!-- {{ duration >= currentMinMinutes * 60?'确认':`确认(${currentMinMinutes * 60 - duration}s)` }} -->
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
@ -121,19 +167,19 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 签名弹框 -->
|
<!-- 签名弹框 -->
|
||||||
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
|
<el-dialog
|
||||||
append-to-body>
|
v-if="signVisible"
|
||||||
|
:visible.sync="signVisible"
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
width="600px"
|
||||||
|
append-to-body
|
||||||
|
>
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
<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>
|
</div>
|
||||||
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName"
|
<SignForm :is-system-doc="currentRow.IsSystemDoc" :document-id="currentRow.Id" :file-name="fileName" :trial-id="trialId" @closeDialog="closeSignDialog" />
|
||||||
:trial-id="trialId" @closeDialog="closeSignDialog" />
|
|
||||||
</el-dialog>
|
</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>
|
</BaseContainer>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -143,8 +189,6 @@ import Pagination from '@/components/Pagination'
|
||||||
import PreviewFile from '@/components/PreviewFile/index'
|
import PreviewFile from '@/components/PreviewFile/index'
|
||||||
import SignForm from './components/SignForm'
|
import SignForm from './components/SignForm'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
|
|
||||||
import attachmentList from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentList'
|
|
||||||
const searchDataDefault = () => {
|
const searchDataDefault = () => {
|
||||||
return {
|
return {
|
||||||
FileTypeId: '',
|
FileTypeId: '',
|
||||||
|
|
@ -158,7 +202,7 @@ const searchDataDefault = () => {
|
||||||
}
|
}
|
||||||
export default {
|
export default {
|
||||||
name: 'TrialAttachments',
|
name: 'TrialAttachments',
|
||||||
components: { BaseContainer, Pagination, PreviewFile, SignForm, attachmentPreview, attachmentList },
|
components: { BaseContainer, Pagination, PreviewFile, SignForm },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
searchData: searchDataDefault(),
|
searchData: searchDataDefault(),
|
||||||
|
|
@ -179,14 +223,7 @@ export default {
|
||||||
fileName: '',
|
fileName: '',
|
||||||
currentUser: zzSessionStorage.getItem('userName'),
|
currentUser: zzSessionStorage.getItem('userName'),
|
||||||
typeOptions: [],
|
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() {
|
mounted() {
|
||||||
|
|
@ -203,16 +240,6 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
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() {
|
getList() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
@ -309,7 +336,7 @@ export default {
|
||||||
// 文档签署已完成,是否关闭弹窗?
|
// 文档签署已完成,是否关闭弹窗?
|
||||||
this.$confirm(this.$t('trials:self-attachment:message:closeDocument')).then(() => {
|
this.$confirm(this.$t('trials:self-attachment:message:closeDocument')).then(() => {
|
||||||
this.previewVisible = false
|
this.previewVisible = false
|
||||||
}).catch(() => { })
|
}).catch(()=>{})
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
this.handleSign(res.Result)
|
this.handleSign(res.Result)
|
||||||
|
|
|
||||||
|
|
@ -729,7 +729,7 @@ export default {
|
||||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||||
this.trialId
|
this.trialId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||||
|
|
@ -766,7 +766,7 @@ export default {
|
||||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||||
this.trialId
|
this.trialId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||||
|
|
@ -801,7 +801,7 @@ export default {
|
||||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
||||||
this.trialId
|
this.trialId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&subjectCode=${this.subjectCode}&subjectId=${
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss">
|
||||||
.preview-wrapper{
|
.preview-wrapper{
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row !important;
|
flex-direction: row !important;
|
||||||
|
|
|
||||||
|
|
@ -1406,7 +1406,7 @@ export default {
|
||||||
)
|
)
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path = ''
|
var path = ''
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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}`
|
||||||
|
|
|
||||||
|
|
@ -203,6 +203,7 @@ export default {
|
||||||
console.log(toolsUtilities)
|
console.log(toolsUtilities)
|
||||||
this.subjectCode = this.$route.query.subjectCode
|
this.subjectCode = this.$route.query.subjectCode
|
||||||
var element = document.getElementById(`viewport${this.index}`)
|
var element = document.getElementById(`viewport${this.index}`)
|
||||||
|
|
||||||
element.addEventListener(VOLUME_NEW_IMAGE, this.handleVolumeNewImage)
|
element.addEventListener(VOLUME_NEW_IMAGE, this.handleVolumeNewImage)
|
||||||
element.addEventListener(Enums.Events.CAMERA_MODIFIED, this.handleCameraModified)
|
element.addEventListener(Enums.Events.CAMERA_MODIFIED, this.handleCameraModified)
|
||||||
element.addEventListener(Enums.Events.VOI_MODIFIED, this.handleVOIModified)
|
element.addEventListener(Enums.Events.VOI_MODIFIED, this.handleVOIModified)
|
||||||
|
|
@ -248,10 +249,8 @@ export default {
|
||||||
this.getOrientationMarker()
|
this.getOrientationMarker()
|
||||||
this.sliderBoxHeight = imageIndex * 100 / (this.seriesInfo.imageMaxLength - 1)
|
this.sliderBoxHeight = imageIndex * 100 / (this.seriesInfo.imageMaxLength - 1)
|
||||||
}
|
}
|
||||||
let properties = viewport.getProperties()
|
|
||||||
if (this.index === 3) {
|
var properties = viewport.getProperties()
|
||||||
properties = viewport.getProperties(`cornerstoneStreamingImageVolume:PT_VOLUME_ID`)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (properties && properties.voiRange) {
|
if (properties && properties.voiRange) {
|
||||||
var { lower, upper } = properties.voiRange
|
var { lower, upper } = properties.voiRange
|
||||||
|
|
@ -325,12 +324,7 @@ export default {
|
||||||
viewport = renderingEngine.getViewport(this.viewportId)
|
viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
if (!viewport) return
|
if (!viewport) return
|
||||||
|
|
||||||
let properties = viewport.getProperties()
|
var 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) {
|
if (properties && properties.voiRange) {
|
||||||
var { lower, upper } = properties.voiRange
|
var { lower, upper } = properties.voiRange
|
||||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
||||||
|
|
@ -568,21 +562,12 @@ export default {
|
||||||
ctx.fillRect(0, 0, rectWidth, rectHeight)
|
ctx.fillRect(0, 0, rectWidth, rectHeight)
|
||||||
},
|
},
|
||||||
setWwWc() {
|
setWwWc() {
|
||||||
let properties = viewport.getProperties()
|
var properties = viewport.getProperties()
|
||||||
if (this.index === 3) {
|
|
||||||
properties = viewport.getProperties(`cornerstoneStreamingImageVolume:PT_VOLUME_ID`)
|
|
||||||
}
|
|
||||||
if (properties && properties.voiRange) {
|
if (properties && properties.voiRange) {
|
||||||
var { lower, upper } = properties.voiRange
|
var { lower, upper } = properties.voiRange
|
||||||
// console.log(lower, upper)
|
const windowWidth = upper - lower
|
||||||
// const windowWidth = upper - lower
|
const windowCenter = (upper + lower) / 2
|
||||||
// const windowCenter = (upper + lower) / 2
|
|
||||||
const { windowWidth, windowCenter } = utilities.windowLevel.toWindowLevel(
|
|
||||||
lower,
|
|
||||||
upper
|
|
||||||
)
|
|
||||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||||
this.$emit('upperRangeChange', Math.round(windowWidth))
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async getScreenshots() {
|
async getScreenshots() {
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,7 @@ import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunc
|
||||||
import { utilities } from '@cornerstonejs/core'
|
import { utilities } from '@cornerstonejs/core'
|
||||||
const { getColormap } = utilities.colormap
|
const { getColormap } = utilities.colormap
|
||||||
function setPetColorMapTransferFunctionForVolumeActor(
|
function setPetColorMapTransferFunctionForVolumeActor(
|
||||||
volumeInfo,
|
volumeInfo
|
||||||
isPT = false
|
|
||||||
) {
|
) {
|
||||||
const { volumeActor, preset } = volumeInfo
|
const { volumeActor, preset } = volumeInfo
|
||||||
const mapper = volumeActor.getMapper()
|
const mapper = volumeActor.getMapper()
|
||||||
|
|
@ -23,14 +22,8 @@ function setPetColorMapTransferFunctionForVolumeActor(
|
||||||
|
|
||||||
// Create scalar opacity function
|
// Create scalar opacity function
|
||||||
const ofun = vtkPiecewiseFunction.newInstance()
|
const ofun = vtkPiecewiseFunction.newInstance()
|
||||||
if (isPT) {
|
ofun.addPoint(0, 0.0)
|
||||||
ofun.addPoint(0, 0.0)
|
ofun.addPoint(0.1, 0.9)
|
||||||
ofun.addPoint(0.1, 1.0)
|
|
||||||
} else {
|
|
||||||
ofun.addPoint(0, 0.0)
|
|
||||||
ofun.addPoint(0.1, 0.9)
|
|
||||||
}
|
|
||||||
|
|
||||||
ofun.addPoint(5, 1.0)
|
ofun.addPoint(5, 1.0)
|
||||||
|
|
||||||
volumeActor.getProperty().setScalarOpacity(0, ofun)
|
volumeActor.getProperty().setScalarOpacity(0, ofun)
|
||||||
|
|
|
||||||
|
|
@ -456,7 +456,7 @@ export default {
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: true,
|
immediate: true,
|
||||||
handler(v, oldv) {
|
handler(v, oldv) {
|
||||||
// console.log(v)
|
console.log(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div ref="container" style="width:100%;height:100%" class="dicom-container">
|
<div ref="container" style="width:100%;height:100%" class="dicom-container">
|
||||||
<!-- 访视阅片 -->
|
<!-- 访视阅片 -->
|
||||||
<div v-if="readingCategory=== 1 && (CriterionType === 7 || ((CriterionType === 1 || CriterionType === 0) && readingVersionEnum === 1)) " class="reading-wrapper">
|
<div v-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType !== 0" 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">
|
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeave">
|
||||||
<!-- 阅片 -->
|
<!-- 阅片 -->
|
||||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||||
|
|
@ -32,7 +29,7 @@
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper">
|
<div v-if="(isReadingTaskViewInOrder === 1 || ((isReadingTaskViewInOrder !== 1) && isShow)) && readingCategory=== 1 && CriterionType === 0" class="reading-wrapper">
|
||||||
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeaveCustomize">
|
<el-tabs v-model="activeName" v-loading="loading" :before-leave="beforeLeaveCustomize">
|
||||||
<!-- 阅片 -->
|
<!-- 阅片 -->
|
||||||
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
<el-tab-pane :label="$t('trials:reading:tabTitle:review')" name="read">
|
||||||
|
|
@ -174,7 +171,6 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getNextTask, readClinicalData, verifyDefaultQuestionBeAnswer } from '@/api/trials'
|
import { getNextTask, readClinicalData, verifyDefaultQuestionBeAnswer } from '@/api/trials'
|
||||||
import VisitReview from './../dicoms3D/components/VisitReview'
|
|
||||||
import ReadPage from './components/ReadPage'
|
import ReadPage from './components/ReadPage'
|
||||||
import CustomizeReadPage from './customize/CustomizeReadPage'
|
import CustomizeReadPage from './customize/CustomizeReadPage'
|
||||||
import ReportPage from './components/ReportPage'
|
import ReportPage from './components/ReportPage'
|
||||||
|
|
@ -191,7 +187,6 @@ import requestPoolManager from '@/utils/request-pool'
|
||||||
export default {
|
export default {
|
||||||
name: 'Reading',
|
name: 'Reading',
|
||||||
components: {
|
components: {
|
||||||
VisitReview,
|
|
||||||
ReadPage,
|
ReadPage,
|
||||||
ReportPage,
|
ReportPage,
|
||||||
GlobalReview,
|
GlobalReview,
|
||||||
|
|
@ -222,7 +217,7 @@ export default {
|
||||||
isReadingTaskViewInOrder: null,
|
isReadingTaskViewInOrder: null,
|
||||||
firstTaskReadingCategory: null,
|
firstTaskReadingCategory: null,
|
||||||
criterionType: null,
|
criterionType: null,
|
||||||
readingTool: 0,
|
readingTool: null,
|
||||||
dialogVisible: false,
|
dialogVisible: false,
|
||||||
TrialReadingCriterionId: null,
|
TrialReadingCriterionId: null,
|
||||||
isNewSubject: null,
|
isNewSubject: null,
|
||||||
|
|
@ -234,8 +229,7 @@ export default {
|
||||||
isFullscreen: false,
|
isFullscreen: false,
|
||||||
tipVisible: false,
|
tipVisible: false,
|
||||||
closeCDVisible: false,
|
closeCDVisible: false,
|
||||||
cdVisitTaskId: '',
|
cdVisitTaskId: ''
|
||||||
readingVersionEnum: null
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -272,7 +266,7 @@ export default {
|
||||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
||||||
// this.isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
// this.isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||||
// this.criterionType = this.$router.currentRoute.query.criterionType
|
// this.criterionType = this.$router.currentRoute.query.criterionType
|
||||||
this.readingTool = this.$router.currentRoute.query.readingTool ? Number(this.$router.currentRoute.query.readingTool) : 0
|
// this.readingTool = this.$router.currentRoute.query.readingTool
|
||||||
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
// this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
// this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
||||||
|
|
||||||
|
|
@ -347,7 +341,6 @@ export default {
|
||||||
localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback)
|
localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback)
|
||||||
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
||||||
this.readingCategory = res.Result.ReadingCategory
|
this.readingCategory = res.Result.ReadingCategory
|
||||||
this.readingVersionEnum = res.Result.ReadingVersionEnum
|
|
||||||
this.questionFormChangeState = false
|
this.questionFormChangeState = false
|
||||||
this.questionFormChangeNum = 0
|
this.questionFormChangeNum = 0
|
||||||
if (this.isExistsClinicalData && this.isNeedReadClinicalData && !this.isReadClinicalData) {
|
if (this.isExistsClinicalData && this.isNeedReadClinicalData && !this.isReadClinicalData) {
|
||||||
|
|
@ -596,10 +589,6 @@ export default {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::v-deep .el-radio__input.is-disabled.is-checked .el-radio__inner {
|
|
||||||
background-color: #428bca;
|
|
||||||
border-color: #428bca;
|
|
||||||
}
|
|
||||||
|
|
||||||
.full-dialog-container{
|
.full-dialog-container{
|
||||||
::v-deep.is-fullscreen .el-dialog__body{
|
::v-deep.is-fullscreen .el-dialog__body{
|
||||||
|
|
|
||||||
|
|
@ -1,276 +0,0 @@
|
||||||
<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>
|
|
||||||
|
|
@ -1,970 +0,0 @@
|
||||||
<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>
|
|
||||||
|
|
@ -1,325 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-if="!!question.GroupName && question.Type==='group'"
|
|
||||||
>
|
|
||||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
|
||||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<template v-else>
|
|
||||||
<el-form-item
|
|
||||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
|
|
||||||
:label="`${question.QuestionName}`"
|
|
||||||
:prop="question.Id"
|
|
||||||
:rules="[
|
|
||||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
|
||||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
|
||||||
]"
|
|
||||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- 输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-if="question.Type==='input'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
/>
|
|
||||||
<!-- 多行文本输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-else-if="question.Type==='textarea'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
|
||||||
maxlength="500"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
/>
|
|
||||||
<!-- 下拉框 -->
|
|
||||||
<el-select
|
|
||||||
v-else-if="question.Type==='select'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode)"
|
|
||||||
clearable
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
>
|
|
||||||
<template v-if="question.TableQuestionType === 1">
|
|
||||||
<el-option
|
|
||||||
v-for="item in organList"
|
|
||||||
:key="item.Id"
|
|
||||||
:label="item[question.DataTableColumn]"
|
|
||||||
:value="item[question.DataTableColumn]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[question.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[question.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="val in question.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
:value="val"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
<!-- 单选 -->
|
|
||||||
<el-radio-group
|
|
||||||
v-else-if="question.Type==='radio'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
>
|
|
||||||
<template v-if="question.DictionaryCode">
|
|
||||||
<el-radio
|
|
||||||
v-for="item of $d[question.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:label="String(item.value)"
|
|
||||||
>
|
|
||||||
{{ item.label }}
|
|
||||||
</el-radio>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="question.TypeValue">
|
|
||||||
<el-radio
|
|
||||||
v-for="val in question.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
>
|
|
||||||
{{ val }}
|
|
||||||
</el-radio>
|
|
||||||
</template>
|
|
||||||
</el-radio-group>
|
|
||||||
<!-- 复选框 -->
|
|
||||||
<el-checkbox-group
|
|
||||||
v-else-if="question.Type==='checkbox'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-for="val in question.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
>
|
|
||||||
{{ val }}
|
|
||||||
</el-checkbox>
|
|
||||||
</el-checkbox-group>
|
|
||||||
<!-- 数值 -->
|
|
||||||
<template v-else-if="question.Type==='number'">
|
|
||||||
<el-input-number
|
|
||||||
v-if="question.ValueType === 0"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:precision="0"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
/>
|
|
||||||
<el-input-number
|
|
||||||
v-else-if="question.ValueType === 3"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
/>
|
|
||||||
<el-input-number
|
|
||||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:precision="digitPlaces"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<el-input
|
|
||||||
v-else-if="question.Type==='calculation'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
<template v-if="question.Unit" slot="append">
|
|
||||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<!-- 上传图像 -->
|
|
||||||
<el-upload
|
|
||||||
v-else-if="question.Type==='upload'"
|
|
||||||
action
|
|
||||||
:accept="accept"
|
|
||||||
:limit="question.ImageCount"
|
|
||||||
:on-preview="handlePictureCardPreview"
|
|
||||||
:before-upload="handleBeforeUpload"
|
|
||||||
:http-request="uploadScreenshot"
|
|
||||||
list-type="picture-card"
|
|
||||||
:on-remove="handleRemove"
|
|
||||||
:file-list="fileList"
|
|
||||||
:class="{disabled:fileList.length >= question.ImageCount}"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
>
|
|
||||||
<i slot="default" class="el-icon-plus" />
|
|
||||||
<div slot="file" slot-scope="{file}">
|
|
||||||
<img
|
|
||||||
class="el-upload-list__item-thumbnail"
|
|
||||||
:src="OSSclientConfig.basePath + file.url"
|
|
||||||
alt=""
|
|
||||||
>
|
|
||||||
<span class="el-upload-list__item-actions">
|
|
||||||
<span
|
|
||||||
class="el-upload-list__item-preview"
|
|
||||||
@click="handlePictureCardPreview(file)"
|
|
||||||
>
|
|
||||||
<i class="el-icon-zoom-in" />
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="readingTaskState < 2"
|
|
||||||
class="el-upload-list__item-delete"
|
|
||||||
@click="handleRemove(file)"
|
|
||||||
>
|
|
||||||
<i class="el-icon-delete" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
|
||||||
<el-dialog
|
|
||||||
v-if="question.Type==='upload'"
|
|
||||||
append-to-body
|
|
||||||
:visible.sync="imgVisible"
|
|
||||||
width="600px"
|
|
||||||
>
|
|
||||||
<el-image :src="imageUrl" width="100%">
|
|
||||||
<div slot="placeholder" class="image-slot">
|
|
||||||
加载中<span class="dot">...</span>
|
|
||||||
</div>
|
|
||||||
</el-image>
|
|
||||||
</el-dialog>
|
|
||||||
</el-form-item>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<question-form-item
|
|
||||||
v-for="(item) in question.Childrens"
|
|
||||||
:key="item.Id"
|
|
||||||
:question="item"
|
|
||||||
:question-form="questionForm"
|
|
||||||
:reading-task-state="readingTaskState"
|
|
||||||
:visitTaskId="visitTaskId"
|
|
||||||
@resetFormItemData="resetFormItemData"
|
|
||||||
@setFormItemData="setFormItemData"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
// import { uploadReadingAnswerImage } from '@/api/trials'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
export default {
|
|
||||||
name: 'QuestionFormItem',
|
|
||||||
props: {
|
|
||||||
questionForm: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
question: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readingTaskState: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
visitTaskId: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
fileList: [],
|
|
||||||
accept: '.png,.jpg,.jpeg',
|
|
||||||
imgVisible: false,
|
|
||||||
imageUrl: '',
|
|
||||||
urls: [],
|
|
||||||
digitPlaces: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['language'])
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
questionForm: {
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
handler(v) {
|
|
||||||
// console.log(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
|
||||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
formItemChange(v, question) {
|
|
||||||
console.log('formItemChange')
|
|
||||||
if (question.Childrens.length > 0) {
|
|
||||||
this.resetChild(question.Childrens)
|
|
||||||
} else {
|
|
||||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetChild(obj) {
|
|
||||||
obj.forEach(i => {
|
|
||||||
this.$emit('resetFormItemData', i.Id)
|
|
||||||
if (i.Childrens && i.Childrens.length > 0) {
|
|
||||||
this.resetChild(i.Childrens)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
resetFormItemData(v) {
|
|
||||||
this.$emit('resetFormItemData', v)
|
|
||||||
},
|
|
||||||
setFormItemData(obj) {
|
|
||||||
this.$emit('setFormItemData', obj)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.mb{
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
.disabled{
|
|
||||||
::v-deep .el-upload--picture-card {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.uploadWrapper{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column !important;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
::v-deep .el-input.is-disabled .el-input__inner{
|
|
||||||
background-color: #646464a1;
|
|
||||||
}
|
|
||||||
::v-deep .el-input-group__append, .el-input-group__prepend{
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
::v-deep .el-form-item__content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
::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>
|
|
||||||
|
|
@ -1,357 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="table-question-form">
|
|
||||||
<div style="display: flex;justify-content: space-between;">
|
|
||||||
<h3 v-if="qsForm.LesionName" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
|
||||||
{{ qsForm.LesionName }}
|
|
||||||
</h3>
|
|
||||||
<!-- 关闭 -->
|
|
||||||
<div>
|
|
||||||
<i class="el-icon-circle-close" style="font-size: 25px;cursor: pointer;" @click="close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('trials:reading:title:lesionType')"
|
|
||||||
prop="LesionType"
|
|
||||||
:rules="[
|
|
||||||
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['blur']},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<!-- 下拉框 -->
|
|
||||||
<el-select
|
|
||||||
v-model="qsForm.LesionType"
|
|
||||||
filterable
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2 || !isBaseLineTask"
|
|
||||||
@change="((val)=>{lesionTypeChange(val)})"
|
|
||||||
>
|
|
||||||
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d.LesionType"
|
|
||||||
v-show="!(isBaseLineTask && item.value === 2)"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item
|
|
||||||
v-for="qs in questions"
|
|
||||||
v-show="qs.ShowQuestion!==2"
|
|
||||||
:key="qs.Id"
|
|
||||||
:label="`${qs.QuestionName}`"
|
|
||||||
:prop="qs.Id"
|
|
||||||
: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.Type!=='group' && qs.Type!=='summary',
|
|
||||||
message:['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<!-- 输入框 -->
|
|
||||||
<template v-if="qs.Type==='input' || qs.Type==='number'">
|
|
||||||
|
|
||||||
<el-input
|
|
||||||
v-if="qs.Type==='input' || qs.Type==='number'"
|
|
||||||
v-model="qsForm[qs.Id]"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName))"
|
|
||||||
@change="((val)=>{formItemChange(val, qs)})"
|
|
||||||
>
|
|
||||||
<template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append">
|
|
||||||
{{ $fd('ValueUnit', parseInt(qs.Unit)) }}
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</template>
|
|
||||||
<!-- 多行文本输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-if="qs.Type==='textarea'"
|
|
||||||
v-model="qsForm[qs.Id]"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
|
||||||
@change="((val)=>{formItemChange(val, qs)})"
|
|
||||||
/>
|
|
||||||
<!-- 下拉框 -->
|
|
||||||
<el-select
|
|
||||||
v-if="qs.Type==='select'"
|
|
||||||
v-model="qsForm[qs.Id]"
|
|
||||||
filterable
|
|
||||||
:placeholder="qs.QuestionMark === 8 ? $t('common:placeholder:selectorsearch') : qs.QuestionMark === 2 ? '' : $t('common:placeholder:select')"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False'|| !!answer.SplitOrMergeLesionName)) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))"
|
|
||||||
@change="((val)=>{formItemChange(val, qs)})"
|
|
||||||
>
|
|
||||||
<template v-if="qs.QuestionMark === 8" #prefix>
|
|
||||||
<span style="padding-left: 5px;">
|
|
||||||
<i class="el-icon-search" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="qs.TableQuestionType === 1">
|
|
||||||
<el-option
|
|
||||||
v-for="item in organList"
|
|
||||||
:key="item.Id"
|
|
||||||
:label="item[qs.DataTableColumn]"
|
|
||||||
:value="item[qs.DataTableColumn]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && isBaseLineTask">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
v-show="(lesionType === 0 && item.value ===0) || (lesionType === 1 && (item.value ===0))"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask">
|
|
||||||
<el-option-group
|
|
||||||
:label="!isNaN(parseFloat(answer.LastTaskState)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(qs.DictionaryCode,parseFloat(answer.LastTaskState))}` : ''"
|
|
||||||
>
|
|
||||||
<!-- 首次分裂的病灶只能选择存在 -->
|
|
||||||
<template v-if="answer.IsFristAdd=== 'True' && answer.SplitOrMergeType === '0'">
|
|
||||||
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
v-show="item.value === 0"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<!-- 首次添加的新病灶不能为无法评估和消失 -->
|
|
||||||
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
v-show="item.value === 0 || item.value === 1"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="item of filterState($d[qs.DictionaryCode])"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-option-group>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="val in qs.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
:value="val"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</el-select>
|
|
||||||
<!-- 单选 -->
|
|
||||||
<el-radio-group
|
|
||||||
v-if="qs.Type==='radio'"
|
|
||||||
v-model="qsForm[qs.id]"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
|
||||||
>
|
|
||||||
<el-radio
|
|
||||||
v-for="val in qs.options.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
>
|
|
||||||
{{ val }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'TableQuestionFormItem',
|
|
||||||
props: {
|
|
||||||
tableInfo: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
answer: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
questionForm: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
organs: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readingTaskState: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isBaseLineTask: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isCurrentTask: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isCurrentTaskAdd: null,
|
|
||||||
lesionType: null,
|
|
||||||
questions: [],
|
|
||||||
organList: [],
|
|
||||||
qsForm: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
questionForm: {
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
handler(v) {
|
|
||||||
if (v.MeasureData) {
|
|
||||||
const { markTool } = v.MeasureData
|
|
||||||
if (markTool === 'Bidirectional') {
|
|
||||||
this.getOrganList(1)
|
|
||||||
} else if (markTool === 'Length') {
|
|
||||||
this.getOrganList(0)
|
|
||||||
} else {
|
|
||||||
this.getOrganList()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.getOrganList()
|
|
||||||
}
|
|
||||||
for (const key in v) {
|
|
||||||
this.$set(this.qsForm, key, v[key])
|
|
||||||
}
|
|
||||||
this.isCurrentTaskAdd = v.IsCurrentTaskAdd
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tableInfo: {
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
handler(v) {
|
|
||||||
if (v) {
|
|
||||||
this.lesionType = v.LesionType
|
|
||||||
this.questions = v.TableQuestions.Questions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
lesionTypeChange(v) {
|
|
||||||
this.$emit('lesionTypeChange', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, newLesionType: v })
|
|
||||||
},
|
|
||||||
formItemChange(v, qs) {
|
|
||||||
const updateArr = []
|
|
||||||
if (qs.QuestionMark === 8 && qs.RelationQuestions.length > 0) {
|
|
||||||
// 当选择部位时,联动器官、位置、是否淋巴结问题答案
|
|
||||||
const index = this.organList.findIndex(item => item[qs.DataTableColumn] === v)
|
|
||||||
if (index > -1) {
|
|
||||||
const selected = this.organList[index]
|
|
||||||
qs.RelationQuestions.map(q => {
|
|
||||||
const val = selected[q.DataTableColumn]
|
|
||||||
updateArr.push({ questionId: q.Id, val: val, questionMark: q.QuestionMark })
|
|
||||||
})
|
|
||||||
updateArr.push({ questionId: 'OrganInfoId', val: selected.OrganInfoId })
|
|
||||||
updateArr.push({ questionId: 'IsCanEditPosition', val: selected.IsCanEditPosition })
|
|
||||||
} else {
|
|
||||||
qs.RelationQuestions.map(q => {
|
|
||||||
updateArr.push({ questionId: q.Id, val: '', questionMark: q.QuestionMark })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$emit('update', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, questionMark: qs.QuestionMark, questionId: qs.Id, val: v, updateArr })
|
|
||||||
},
|
|
||||||
getOrganList(isLymphNodes = null) {
|
|
||||||
const idx = this.organs.findIndex(i => i.LesionType === this.questionForm.LesionType)
|
|
||||||
if (idx > -1) {
|
|
||||||
const arr = this.organs[idx].OrganList
|
|
||||||
|
|
||||||
if (!isNaN(parseInt(isLymphNodes))) {
|
|
||||||
this.organList = arr.filter((item) => item.IsLymphNodes === parseInt(isLymphNodes))
|
|
||||||
} else {
|
|
||||||
this.organList = arr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
filterState(arr) {
|
|
||||||
if (!this.isBaseLineTask) {
|
|
||||||
const isLymphLesion = this.questionForm.IsLymphNodes
|
|
||||||
const lesionLength = this.questionForm.LesionLength
|
|
||||||
const lesionShort = this.questionForm.LesionShort
|
|
||||||
const bLesionL = !isNaN(parseFloat(this.questionForm.BaseLineMajorAxis)) ? parseFloat(this.questionForm.BaseLineMajorAxis) : 0
|
|
||||||
const bLesionS = !isNaN(parseFloat(this.questionForm.BaseLineShortAxis)) ? parseFloat(this.questionForm.BaseLineShortAxis) : 0
|
|
||||||
if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort < bLesionS) {
|
|
||||||
arr = arr.filter(i => i.value !== 1)
|
|
||||||
} else if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort >= 10 && lesionShort > bLesionS) {
|
|
||||||
arr = arr.filter(i => i.value === 0 || i.value === 1)
|
|
||||||
} else if (this.lesionType === 1 && isLymphLesion === 0 && this.questionForm.MeasureData && (this.questionForm.MeasureData.markTool === 'Length' || this.questionForm.MeasureData.markTool === 'Bidirectional') && lesionLength < bLesionL) {
|
|
||||||
arr = arr.filter(i => i.value !== 1)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
} else {
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.$emit('close', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.table-question-form{
|
|
||||||
::v-deep .el-form-item__label{
|
|
||||||
color: #c3c3c3;
|
|
||||||
}
|
|
||||||
::v-deep .el-input .el-input__inner{
|
|
||||||
background-color: transparent;
|
|
||||||
color: #ddd;
|
|
||||||
border: 1px solid #5e5e5e;
|
|
||||||
}
|
|
||||||
::v-deep .el-form-item{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
::v-deep .el-form-item__content{
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
::v-deep .el-input.is-disabled .el-input__inner{
|
|
||||||
background-color: #646464a1;
|
|
||||||
}
|
|
||||||
::v-deep .el-select.is-disabled .el-input__inner{
|
|
||||||
background-color: #646464a1;
|
|
||||||
}
|
|
||||||
::v-deep .el-button--mini, .el-button--mini.is-round {
|
|
||||||
padding: 7px 10px;
|
|
||||||
}
|
|
||||||
.el-form-item__content
|
|
||||||
.el-select{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.input-width1{
|
|
||||||
width: calc(100% - 60px)!important;
|
|
||||||
}
|
|
||||||
.input-width2{
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,914 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="report-wrapper">
|
|
||||||
<el-card v-loading="loading" shadow="never">
|
|
||||||
<div slot="header" class="clearfix report-header">
|
|
||||||
<!-- 电子影像病例报告表(eICRF) -->
|
|
||||||
<h3 style="margin:0;padding:0;">{{ $t('trials:readingReport:title:eicrf') }}</h3>
|
|
||||||
<div style="margin-left:auto">
|
|
||||||
<el-switch
|
|
||||||
v-model="isShowDetail"
|
|
||||||
:active-text="$t('trials:readingReport:title:expandDetails')"
|
|
||||||
:inactive-text="$t('trials:readingReport:title:collapseDetails')"
|
|
||||||
style="margin-right:5px;"
|
|
||||||
@change="handleShowDetail"
|
|
||||||
/>
|
|
||||||
<el-button
|
|
||||||
v-if="readingTaskState<2"
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="skipTask"
|
|
||||||
>
|
|
||||||
<!-- 跳过 -->
|
|
||||||
{{ $t('trials:readingReport:button:skip') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="readingTaskState<2"
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="getReportInfo(false)"
|
|
||||||
>
|
|
||||||
<!-- 刷新 -->
|
|
||||||
{{ $t('trials:readingReport:button:refresh') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="readingTaskState<2 && criterionType !== 10"
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="handleSave(true)"
|
|
||||||
>
|
|
||||||
<!-- 保存 -->
|
|
||||||
{{ $t('common:button:save') }}
|
|
||||||
</el-button>
|
|
||||||
<el-button
|
|
||||||
v-if="readingTaskState<2"
|
|
||||||
type="primary"
|
|
||||||
size="small"
|
|
||||||
@click="beforeLeave"
|
|
||||||
>
|
|
||||||
<!-- 提交 -->
|
|
||||||
{{ $t('common:button:submit') }}
|
|
||||||
</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div ref="tableWrapper" style="height:100%;overflow-y: auto;">
|
|
||||||
<el-table
|
|
||||||
v-if="height"
|
|
||||||
ref="reportList"
|
|
||||||
:data="taskQuestions"
|
|
||||||
row-key="Id"
|
|
||||||
border
|
|
||||||
:expand-row-keys="expandedRows"
|
|
||||||
:height="height"
|
|
||||||
: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" :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) ? '#f66' : '#fff'}">{{ scope.row.QuestionName }}</span>
|
|
||||||
<span
|
|
||||||
v-else
|
|
||||||
style="font-weight: bold;font-size: 16px;color: #f44336;"
|
|
||||||
>
|
|
||||||
{{ language==='en'?scope.row.GroupEnName: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="150px"
|
|
||||||
>
|
|
||||||
<template slot="header">
|
|
||||||
<div v-if="task.IsCurrentTask">
|
|
||||||
<div>
|
|
||||||
{{ task.BlindName }}
|
|
||||||
</div>
|
|
||||||
</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">
|
|
||||||
<span :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) || (scope.row.QuestionMark === 12) || scope.row.HighlightAnswerList.includes(`${scope.row.Answers[task.VisitTaskId]}`) ? '#f66' : '#fff'}">
|
|
||||||
<template v-if="task.VisitTaskId === visitTaskId && readingTaskState < 2 && [13,14,15,42].includes(scope.row.QuestionType)">
|
|
||||||
<!-- 是否存在疾病(基线时可修改) -->
|
|
||||||
<template v-if="task.IsBaseLine && scope.row.QuestionType=== 15">
|
|
||||||
<el-select
|
|
||||||
v-if="scope.row.Type==='select' && scope.row.DictionaryCode"
|
|
||||||
v-model="currentExistDisease"
|
|
||||||
size="mini"
|
|
||||||
@change="handleExistDiseaseChange"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
<!-- 整体肿瘤评估(非基线可修改) -->
|
|
||||||
<template v-else-if="!task.IsBaseLine && (scope.row.QuestionType=== 13 || scope.row.QuestionType=== 42)">
|
|
||||||
<el-select
|
|
||||||
v-if="scope.row.Type==='select' && scope.row.DictionaryCode"
|
|
||||||
v-model="currentEvaluateResult"
|
|
||||||
size="mini"
|
|
||||||
@change="handleEvaluateResultChange"
|
|
||||||
>
|
|
||||||
<template v-if="criterionType === 1 && tLesionCount">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
|
||||||
v-show="(!task.IsBaseLine && item.value > -1) && (task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1) && (item.value !== 1 && item.value !== 3)"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="criterionType === 1 && ntLesionCount">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
|
||||||
v-show="(!task.IsBaseLine && item.value > -1) && (task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1) && (item.value !== 1)"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
|
||||||
v-show="(!task.IsBaseLine && item.value > -1) && (task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1)"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
</template>
|
|
||||||
<!-- <template v-else-if="task.IsBaseLine && scope.row.QuestionType=== 13">
|
|
||||||
{{ $fd(scope.row.DictionaryCode, currentEvaluateResult) }}
|
|
||||||
</template> -->
|
|
||||||
<!-- 访视点备注(是否存在疾病与系统不一致或者整体肿瘤评估与系统不一致时,必填) -->
|
|
||||||
<!-- tumorEvaluate && task.VisitTaskId === visitTaskId && scope.row.QuestionType=== 14 && (currentEvaluateResult !== tumorEvaluate || currentExistDisease !== isExistDisease) -->
|
|
||||||
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.QuestionType=== 14 ">
|
|
||||||
<!-- v-if="tumorEvaluate && (currentEvaluateResult !== tumorEvaluate || currentExistDisease !== isExistDisease)" -->
|
|
||||||
<template>
|
|
||||||
<!-- 输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-if="scope.row.Type==='input'"
|
|
||||||
v-model="currentTaskReason"
|
|
||||||
size="mini"
|
|
||||||
@change="evaluateReasonChange"
|
|
||||||
/>
|
|
||||||
<el-input
|
|
||||||
v-else-if="scope.row.Type==='textarea'"
|
|
||||||
v-model="currentTaskReason"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
|
||||||
size="mini"
|
|
||||||
maxlength="500"
|
|
||||||
@change="evaluateReasonChange"
|
|
||||||
/>
|
|
||||||
<!-- 系统评估结果为:xxx,与当前调整的结果不一致,请填写调整原因 -->
|
|
||||||
<p v-if="currentEvaluateResult !== tumorEvaluate" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;" v-html="getWarningText()" />
|
|
||||||
<p v-else-if="currentExistDisease !== isExistDisease" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;">{{ $t('trials:readingReport:title:sysEvaluationRes') }}<span style="color:red">{{ $fd('ExistDisease',isExistDisease) }}</span>{{ $t('trials:readingReport:message:msg1') }}
|
|
||||||
</p>
|
|
||||||
</template>
|
|
||||||
<!-- <template v-else>
|
|
||||||
<span>{{ currentTaskReason }}</span>
|
|
||||||
</template> -->
|
|
||||||
|
|
||||||
</template>
|
|
||||||
<template v-else-if="scope.row.DictionaryCode">
|
|
||||||
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
{{ scope.row.Answers[task.VisitTaskId] }}
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else-if="scope.row.QuestionType=== 15">
|
|
||||||
<el-tooltip v-if="getAnswerInfo(scope.row.Answer,task.VisitTaskId,'IsGlobalChange')" :content="`${$t('trials:reading:warnning:msg55')}${$fd(scope.row.DictionaryCode, getAnswerInfo(scope.row.Answer,task.VisitTaskId,'GlobalChangeAnswer'))}`" placement="top" effect="light">
|
|
||||||
<span style="color:red;"> {{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
<span v-else>{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else-if="scope.row.QuestionType=== 13 || scope.row.QuestionType=== 42">
|
|
||||||
<el-tooltip v-if="getAnswerInfo(scope.row.Answer,task.VisitTaskId,'IsGlobalChange')" :content="`${$t('trials:reading:warnning:msg55')}${$fd(scope.row.DictionaryCode, getAnswerInfo(scope.row.Answer,task.VisitTaskId,'GlobalChangeAnswer'))}`" placement="top" effect="light">
|
|
||||||
<span style="color:red;"> {{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
|
||||||
</el-tooltip>
|
|
||||||
<span v-else>{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="scope.row.QuestionType=== 22">
|
|
||||||
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? $t('trials:readingReport:title:unknow') : scope.row.Answers[task.VisitTaskId] }}
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<template v-else-if="scope.row.DictionaryCode">
|
|
||||||
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
|
||||||
</template>
|
|
||||||
<template v-else-if="criterionType === 10">
|
|
||||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]}` }}
|
|
||||||
</template>
|
|
||||||
<template v-else-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
|
||||||
{{ `${scope.row.Answers[task.VisitTaskId]}` }}
|
|
||||||
<span v-if="scope.row.Answers[task.VisitTaskId] !== 'NA' && !isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))">{{ `${$fd('ValueUnit',scope.row.Unit)}` }}</span>
|
|
||||||
</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>
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</div>
|
|
||||||
</el-card>
|
|
||||||
<!-- 附加评估 -->
|
|
||||||
<el-dialog
|
|
||||||
v-if="additionalAssessmentsDig.visible"
|
|
||||||
:visible.sync="additionalAssessmentsDig.visible"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:title="additionalAssessmentsDig.title"
|
|
||||||
width="600px"
|
|
||||||
>
|
|
||||||
<additional-assessment
|
|
||||||
:questions="assessmentQuestions"
|
|
||||||
:visit-task-id="visitTaskId"
|
|
||||||
@close="additionalAssessmentsDig.visible = false"
|
|
||||||
@sign="sign"
|
|
||||||
/>
|
|
||||||
</el-dialog>
|
|
||||||
<!-- 签名框 -->
|
|
||||||
<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 { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getTaskAdditionalQuestion } 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 { getToken } from '@/utils/auth'
|
|
||||||
// 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'
|
|
||||||
export default {
|
|
||||||
name: 'ReportPage',
|
|
||||||
components: { SignForm, AdditionalAssessment },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
currentUser: zzSessionStorage.getItem('userName'),
|
|
||||||
signVisible: false,
|
|
||||||
signCode: null,
|
|
||||||
visitTaskList: [],
|
|
||||||
taskQuestions: [],
|
|
||||||
loading: false,
|
|
||||||
answers: [],
|
|
||||||
readingTaskState: 2,
|
|
||||||
tumorEvaluate: null,
|
|
||||||
currentEvaluateResult: null,
|
|
||||||
isExistDisease: null,
|
|
||||||
currentExistDisease: null,
|
|
||||||
currentTaskReason: '',
|
|
||||||
answerArr: [],
|
|
||||||
questions: [],
|
|
||||||
isShowDetail: false,
|
|
||||||
criterionType: 0,
|
|
||||||
height: 0,
|
|
||||||
additionalAssessmentsDig: { visible: false, title: this.$t('trials:trials-panel:setting:reading-unit:TrialCriterionAdditionalAssessmentTypeList') },
|
|
||||||
assessmentQuestions: [],
|
|
||||||
tLesionCount: null,
|
|
||||||
ntLesionCount: null,
|
|
||||||
openWindow: null,
|
|
||||||
expandedRows: [],
|
|
||||||
taskInfo: {},
|
|
||||||
visitTaskId: '',
|
|
||||||
isBaselineTask: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['language'])
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
taskQuestions() {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.getTableHeight()
|
|
||||||
this.$refs.reportList && this.$refs.reportList.doLayout()
|
|
||||||
this.setScrollTop()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
},
|
|
||||||
created() { this.getTableHeight() },
|
|
||||||
mounted() {
|
|
||||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
|
||||||
this.criterionType = this.taskInfo.CriterionType
|
|
||||||
this.visitTaskId = this.taskInfo.VisitTaskId
|
|
||||||
this.isBaselineTask = this.taskInfo.IsBaseLine
|
|
||||||
window.addEventListener('resize', () => {
|
|
||||||
this.handleResize()
|
|
||||||
this.setScrollTop()
|
|
||||||
})
|
|
||||||
this.getReportInfo()
|
|
||||||
},
|
|
||||||
beforeDestroy() {
|
|
||||||
if (this.openWindow) {
|
|
||||||
this.openWindow.close()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
myConfirm(msg) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
this.$confirm(msg, {
|
|
||||||
type: 'warning',
|
|
||||||
showCancelButton: true
|
|
||||||
}).then(() => {
|
|
||||||
resolve(true)
|
|
||||||
}).catch(() => {
|
|
||||||
resolve(false)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
},
|
|
||||||
async beforeLeave() {
|
|
||||||
this.handleConfirm()
|
|
||||||
},
|
|
||||||
getAnswerInfo(answerArr, visitTaskId, prop) {
|
|
||||||
var i = answerArr.findIndex(i => i.VisitTaskId === visitTaskId)
|
|
||||||
if (i === -1) return ''
|
|
||||||
var val = answerArr[i][prop]
|
|
||||||
return isNaN(parseInt(val)) ? val : parseInt(val)
|
|
||||||
},
|
|
||||||
getTableHeight() {
|
|
||||||
this.height = window.innerHeight - 170
|
|
||||||
},
|
|
||||||
async getReportInfo(IsCalculate) {
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
var params = {
|
|
||||||
visitTaskId: this.visitTaskId,
|
|
||||||
trialId: this.$router.currentRoute.query.trialId,
|
|
||||||
IsCalculate: IsCalculate !== false
|
|
||||||
}
|
|
||||||
const res = await getReadingReportEvaluation(params)
|
|
||||||
if (res.IsSuccess) {
|
|
||||||
this.readingTaskState = res.Result.ReadingTaskState
|
|
||||||
this.tumorEvaluate = res.Result.CalculateResult && res.Result.CalculateResult.TumorEvaluate ? parseInt(res.Result.CalculateResult.TumorEvaluate) : null
|
|
||||||
this.isExistDisease = res.Result.CalculateResult && res.Result.CalculateResult.IsExistDisease ? parseInt(res.Result.CalculateResult.IsExistDisease) : null
|
|
||||||
this.answerArr = []
|
|
||||||
this.questions = res.Result.TaskQuestions.concat()
|
|
||||||
this.visitTaskList = res.Result.VisitTaskList
|
|
||||||
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
|
|
||||||
this.taskQuestions = []
|
|
||||||
taskQuestions.forEach(item => {
|
|
||||||
this.$set(this.taskQuestions, this.taskQuestions.length, item)
|
|
||||||
})
|
|
||||||
const tLesion = res.Result.LesionCountList.find(i => i.LesionType === 0)
|
|
||||||
this.tLesionCount = tLesion ? tLesion.Count : 0
|
|
||||||
const ntLesion = res.Result.LesionCountList.find(i => i.LesionType === 1)
|
|
||||||
this.ntLesionCount = ntLesion ? ntLesion.Count : 0
|
|
||||||
this.setScrollTop()
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
} catch (e) {
|
|
||||||
this.loading = false
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setScrollTop(a) {
|
|
||||||
setTimeout(() => {
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.$refs.reportList) {
|
|
||||||
this.getTableHeight()
|
|
||||||
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}, 50)
|
|
||||||
},
|
|
||||||
getQuestions(questions, isNTFilterLength, lesionType, isLymphNodes) {
|
|
||||||
const arr = []
|
|
||||||
if (questions.length !== 0) {
|
|
||||||
questions.forEach((item) => {
|
|
||||||
if (this.criterionType === 21) {
|
|
||||||
if (!this.isShowDetail) {
|
|
||||||
if (!item.RowId) {
|
|
||||||
this.expandedRows.push(item.Id)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.expandedRows.push(item.Id)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.expandedRows.push(item.Id)
|
|
||||||
}
|
|
||||||
// 过滤病灶标识 病灶名称 部位 器官 位置 是否淋巴结
|
|
||||||
// 非靶病灶和新病灶 过滤长径和短径信息
|
|
||||||
// 非淋巴结靶病灶 过滤短径
|
|
||||||
|
|
||||||
lesionType = item.LesionType
|
|
||||||
var filterArr = [7]
|
|
||||||
// 0:靶病灶、 5:新靶病灶
|
|
||||||
// 1:非靶病灶、2:新病灶、6:新非靶病灶、7:其它既往新病灶、8:触发irecisit后的新病灶
|
|
||||||
// 0:长径,1:短径,2:是否淋巴结,3:自增ID,4:病灶名称,5:所在器官,6:所在位置,7:状态,8:所在部位,10:部位描述
|
|
||||||
// 1105:是否可测量,1106:肝脏分段
|
|
||||||
if ((item.LesionType === 1 || item.LesionType === 2 || item.LesionType === 6 || item.LesionType === 7 || item.LesionType === 8) && isNTFilterLength) {
|
|
||||||
filterArr = [0, 1, 3, 4, 5, 6, 2, 8, 10, 7, 1105]
|
|
||||||
} 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 === 7 || this.criterionType === 17)) {
|
|
||||||
filterArr.push(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isLymphNodes === 0) {
|
|
||||||
filterArr.push(1)
|
|
||||||
}
|
|
||||||
if (!(filterArr.includes(item.QuestionMark))) {
|
|
||||||
const obj = item
|
|
||||||
obj.Answers = {}
|
|
||||||
if (item.RowIndex > 0) {
|
|
||||||
try {
|
|
||||||
var idx = item.Childrens.findIndex(i => i.QuestionMark === 8)
|
|
||||||
var idxLoc = item.Childrens.findIndex(i => i.QuestionMark === 10)
|
|
||||||
var state = item.Childrens.findIndex(i => i.QuestionMark === 7)
|
|
||||||
if (idx > -1) {
|
|
||||||
if (item.Childrens[idx].Answer.length > 0) {
|
|
||||||
var k = item.Childrens[idx].Answer.findIndex(v => v.Answer !== '')
|
|
||||||
var part = ''
|
|
||||||
if (obj.IsCanEditPosition) {
|
|
||||||
part = `${item.Childrens[idx].Answer[k].Answer}--${item.Childrens[idxLoc].Answer[k].Answer}`
|
|
||||||
} else {
|
|
||||||
part = `${item.Childrens[idx].Answer[k].Answer}`
|
|
||||||
}
|
|
||||||
if (item.SplitOrMergeLesionName && k > -1) {
|
|
||||||
// obj.QuestionName = `${obj.QuestionName} --${part} (Split from ${item.SplitOrMergeLesionName})`
|
|
||||||
obj.QuestionName = `${obj.QuestionName} --${part}`
|
|
||||||
var Answers = {}
|
|
||||||
if (state >= 0) {
|
|
||||||
this.visitTaskList.forEach(v => {
|
|
||||||
const o = item.Childrens[state].Answer.find(v1 => {
|
|
||||||
return v1.VisitTaskId === v.VisitTaskId
|
|
||||||
})
|
|
||||||
if (o) {
|
|
||||||
Answers[o.VisitTaskId] = this.$fd(item.Childrens[state].DictionaryCode, parseInt(o.Answer))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.$set(obj, 'Answers', Answers)
|
|
||||||
// obj.QuestionName = `${obj.QuestionName} `
|
|
||||||
} else if (!item.SplitOrMergeLesionName && k > -1) {
|
|
||||||
obj.QuestionName = `${obj.QuestionName}--${part}`
|
|
||||||
const Answers = {}
|
|
||||||
if (state >= 0) {
|
|
||||||
this.visitTaskList.forEach(v => {
|
|
||||||
const o = item.Childrens[state].Answer.find(v1 => {
|
|
||||||
return v1.VisitTaskId === v.VisitTaskId
|
|
||||||
})
|
|
||||||
if (o) {
|
|
||||||
Answers[o.VisitTaskId] = this.$fd(item.Childrens[state].DictionaryCode, parseInt(o.Answer))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.$set(obj, 'Answers', Answers)
|
|
||||||
// obj.QuestionName = `${obj.QuestionName} `
|
|
||||||
} else {
|
|
||||||
obj.QuestionName = `${obj.QuestionName} `
|
|
||||||
}
|
|
||||||
if (item.ReportMark) {
|
|
||||||
obj.QuestionName = `${obj.QuestionName} (${item.ReportMark})`
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
item.Childrens.forEach(v => {
|
|
||||||
this.$set(v, 'isLymphNodes', isLymphNodes)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (this.criterionType === 21) {
|
|
||||||
var liverSegmentIdx = item.Childrens.findIndex(i => i.QuestionMark === 1106)
|
|
||||||
if (liverSegmentIdx > -1) {
|
|
||||||
if (item.Childrens[liverSegmentIdx].Answer.length > 0) {
|
|
||||||
const v = item.Childrens[liverSegmentIdx].Answer[0].Answer
|
|
||||||
obj.QuestionName = this.$fd(item.Childrens[liverSegmentIdx].DictionaryCode, parseInt(v))
|
|
||||||
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 => {
|
|
||||||
return v1.VisitTaskId === v.VisitTaskId
|
|
||||||
})
|
|
||||||
if (o) {
|
|
||||||
Answers[o.VisitTaskId] = isNaN(parseFloat(o.Answer)) ? o.Answer : `${o.Answer}%`
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
this.$set(obj, 'Answers', Answers)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
item.Answer.forEach(i => {
|
|
||||||
if (item.DictionaryCode) {
|
|
||||||
obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
|
||||||
} else {
|
|
||||||
obj.Answers[i.VisitTaskId] = i.Answer
|
|
||||||
}
|
|
||||||
})
|
|
||||||
if (item.QuestionType === 15) {
|
|
||||||
this.currentExistDisease = obj.Answers[this.visitTaskId]
|
|
||||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 15 })
|
|
||||||
}
|
|
||||||
if (item.QuestionType === 13 || item.QuestionType === 42) {
|
|
||||||
this.currentEvaluateResult = obj.Answers[this.visitTaskId]
|
|
||||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: item.QuestionType })
|
|
||||||
}
|
|
||||||
if (item.QuestionType === 14) {
|
|
||||||
this.currentTaskReason = obj.Answers[this.visitTaskId]
|
|
||||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 })
|
|
||||||
}
|
|
||||||
if (item.Childrens.length >= 1) {
|
|
||||||
obj.Childrens = this.getQuestions(item.Childrens, isNTFilterLength, lesionType, isLymphNodes)
|
|
||||||
}
|
|
||||||
arr.push(obj)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
},
|
|
||||||
handleShowDetail(val) {
|
|
||||||
this.getReportInfo()
|
|
||||||
// this.taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null)
|
|
||||||
},
|
|
||||||
handleExistDiseaseChange(val) {
|
|
||||||
// this.currentExistDisease = parseInt(val)
|
|
||||||
if (val === this.isExistDisease && this.tumorEvaluate === this.currentEvaluateResult) {
|
|
||||||
this.currentTaskReason = ''
|
|
||||||
this.evaluateReasonChange('')
|
|
||||||
}
|
|
||||||
this.currentTaskReason = ''
|
|
||||||
this.evaluateReasonChange('')
|
|
||||||
var idx = this.answerArr.findIndex(i => i.questionType === 15)
|
|
||||||
if (idx > -1) {
|
|
||||||
this.answerArr[idx].answer = val
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleEvaluateResultChange(val) {
|
|
||||||
// this.currentEvaluateResult = parseInt(val)
|
|
||||||
if (val === this.tumorEvaluate && this.isExistDisease === this.currentExistDisease) {
|
|
||||||
this.currentTaskReason = ''
|
|
||||||
this.evaluateReasonChange('')
|
|
||||||
}
|
|
||||||
this.currentTaskReason = ''
|
|
||||||
this.evaluateReasonChange('')
|
|
||||||
var idx = this.answerArr.findIndex(i => i.questionType === 13 || i.questionType === 42)
|
|
||||||
if (idx > -1) {
|
|
||||||
this.answerArr[idx].answer = val
|
|
||||||
}
|
|
||||||
this.setScrollTop()
|
|
||||||
},
|
|
||||||
|
|
||||||
evaluateReasonChange(val) {
|
|
||||||
var idx = this.answerArr.findIndex(i => i.questionType === 14)
|
|
||||||
if (idx > -1) {
|
|
||||||
this.answerArr[idx].answer = val
|
|
||||||
}
|
|
||||||
},
|
|
||||||
async handleConfirm() {
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
await this.handleSave(false)
|
|
||||||
await verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId })
|
|
||||||
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
|
||||||
var isBaseline = this.visitTaskList[i].IsBaseLine
|
|
||||||
if (isBaseline) {
|
|
||||||
const res = await getTaskAdditionalQuestion({ visitTaskId: this.visitTaskId })
|
|
||||||
this.assessmentQuestions = res.Result
|
|
||||||
if (this.assessmentQuestions.length > 0) {
|
|
||||||
// 打开附加评估框
|
|
||||||
this.additionalAssessmentsDig.visible = true
|
|
||||||
} else {
|
|
||||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
|
||||||
this.signCode = ImageAssessmentReportConfirmation
|
|
||||||
this.signVisible = true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
|
||||||
this.signCode = ImageAssessmentReportConfirmation
|
|
||||||
this.signVisible = true
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
} catch (e) {
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
sign() {
|
|
||||||
this.additionalAssessmentsDig.visible = false
|
|
||||||
this.$nextTick(() => {
|
|
||||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
|
||||||
this.signCode = ImageAssessmentReportConfirmation
|
|
||||||
this.signVisible = true
|
|
||||||
})
|
|
||||||
},
|
|
||||||
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
|
|
||||||
// window.location.reload()
|
|
||||||
window.opener.postMessage('refreshTaskList', window.location)
|
|
||||||
|
|
||||||
// 设置当前任务阅片状态为已读
|
|
||||||
this.readingTaskState = 2
|
|
||||||
this.$emit('setReadingTaskState', 2)
|
|
||||||
const res = await getAutoCutNextTask()
|
|
||||||
var 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)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
window.opener.postMessage('refreshTaskList', window.location)
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
} catch (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(async(resolve, reject) => {
|
|
||||||
var isBeill
|
|
||||||
var evaluateResult = ''
|
|
||||||
var evaluateAjustReason = ''
|
|
||||||
this.answers = []
|
|
||||||
var isExistEvaluateResult = false
|
|
||||||
this.answerArr.map(item => {
|
|
||||||
if (item.questionType === 13 || item.questionType === 42) {
|
|
||||||
evaluateResult = item.answer
|
|
||||||
isExistEvaluateResult = true
|
|
||||||
}
|
|
||||||
if (item.questionType === 14) {
|
|
||||||
evaluateAjustReason = item.answer
|
|
||||||
}
|
|
||||||
if (item.questionType === 15) {
|
|
||||||
isBeill = item.answer
|
|
||||||
}
|
|
||||||
this.answers.push({ id: item.id, answer: item.answer })
|
|
||||||
})
|
|
||||||
console.log(this.currentExistDisease, this.isExistDisease, evaluateAjustReason, isBeill)
|
|
||||||
if (this.currentExistDisease !== this.isExistDisease && !evaluateAjustReason) {
|
|
||||||
this.$confirm(this.$t('trials:readingReport:message:msg2'), {
|
|
||||||
type: 'warning',
|
|
||||||
showCancelButton: false,
|
|
||||||
callback: action => {}
|
|
||||||
})
|
|
||||||
resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (isExistEvaluateResult && (evaluateResult === null && !this.isBaselineTask)) {
|
|
||||||
// 请将疗效评估信息填写完整
|
|
||||||
this.$confirm(this.$t('trials:readingReport:message:msg2'), {
|
|
||||||
type: 'warning',
|
|
||||||
showCancelButton: false,
|
|
||||||
callback: action => {}
|
|
||||||
})
|
|
||||||
resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) {
|
|
||||||
// 请填写整体评估调整原因
|
|
||||||
this.$confirm(this.$t('trials:readingReport:message:msg3'), {
|
|
||||||
type: 'warning',
|
|
||||||
showCancelButton: false,
|
|
||||||
callback: action => {}
|
|
||||||
})
|
|
||||||
resolve()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
var params = {
|
|
||||||
visitTaskId: this.visitTaskId,
|
|
||||||
answers: this.answers
|
|
||||||
}
|
|
||||||
const res = await changeDicomReadingQuestionAnswer(params)
|
|
||||||
if (res.IsSuccess && isPrompt) {
|
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
|
||||||
}
|
|
||||||
this.loading = false
|
|
||||||
resolve()
|
|
||||||
} catch (e) {
|
|
||||||
this.loading = false
|
|
||||||
reject()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
getWarningText() {
|
|
||||||
var sysRes = ''
|
|
||||||
var curRes = ''
|
|
||||||
if (this.CriterionType === 2) {
|
|
||||||
sysRes = this.$fd('ImagingOverallAssessment_Lugano', this.tumorEvaluate)
|
|
||||||
curRes = this.$fd('ImagingOverallAssessment_Lugano', this.currentEvaluateResult)
|
|
||||||
} else {
|
|
||||||
sysRes = this.$fd('OverallAssessment', this.tumorEvaluate)
|
|
||||||
curRes = this.$fd('OverallAssessment', this.currentEvaluateResult)
|
|
||||||
}
|
|
||||||
if (!curRes) {
|
|
||||||
return ''
|
|
||||||
}
|
|
||||||
const msg = this.$t('trials:readingReport:message:msg9').replace('xxx', '<font color="red">' + sysRes + '</font>').replace('yyy', '<font color="red">' + curRes + '</font>')
|
|
||||||
return msg
|
|
||||||
},
|
|
||||||
async skipTask() {
|
|
||||||
try {
|
|
||||||
// 是否确认跳过?
|
|
||||||
const confirm = await this.$confirm(
|
|
||||||
this.$t('trials:readingReport:message:skipConfirm'),
|
|
||||||
{
|
|
||||||
type: 'warning',
|
|
||||||
distinguishCancelAndClose: true
|
|
||||||
}
|
|
||||||
)
|
|
||||||
if (confirm !== 'confirm') return
|
|
||||||
this.loading = true
|
|
||||||
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
|
|
||||||
this.loading = false
|
|
||||||
if (res.IsSuccess) {
|
|
||||||
window.location.reload()
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
this.loading = false
|
|
||||||
console.log(e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.report-wrapper{
|
|
||||||
|
|
||||||
height: 100%;
|
|
||||||
padding: 10px 0px;
|
|
||||||
// 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{
|
|
||||||
display:flex;flex-direction: column;height: 100%;
|
|
||||||
background-color: #000;
|
|
||||||
color: #ffffff;
|
|
||||||
border:none;
|
|
||||||
::v-deep .el-card__body{
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ::v-deep .el-table__cell{
|
|
||||||
// background-color: #000;
|
|
||||||
// color: #ffffff;
|
|
||||||
// }
|
|
||||||
// ::v-deep .el-table{
|
|
||||||
// background-color: #000;
|
|
||||||
// color: #ffffff;
|
|
||||||
// }
|
|
||||||
// ::v-deep .el-table__cell{
|
|
||||||
// background-color: #000;
|
|
||||||
// color: #ffffff;
|
|
||||||
// }
|
|
||||||
|
|
||||||
::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-switch__label{
|
|
||||||
color:#fff;
|
|
||||||
}
|
|
||||||
::v-deep .el-switch__label.is-active{
|
|
||||||
color: #428bca;
|
|
||||||
}
|
|
||||||
.colorOfRed{
|
|
||||||
color: #f66;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,333 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-loading="loading" class="study-wrapper">
|
|
||||||
<div class="study-info">
|
|
||||||
<div
|
|
||||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
|
|
||||||
:title="taskInfo.SubjectCode"
|
|
||||||
>
|
|
||||||
{{ taskInfo.SubjectCode }}
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo"
|
|
||||||
:title="visitTaskInfo.TaskBlindName"
|
|
||||||
>
|
|
||||||
{{ visitTaskInfo.TaskBlindName }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="ps">
|
|
||||||
<el-collapse v-model="activeNames">
|
|
||||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
|
||||||
<template slot="title">
|
|
||||||
<div
|
|
||||||
v-if="!study.IsCriticalSequence"
|
|
||||||
class="dicom-desc"
|
|
||||||
>
|
|
||||||
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
|
||||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
|
||||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
|
||||||
<span v-if="study.StudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName }}</span>
|
|
||||||
<span v-else :title="study.Modalities" style="margin-left: 5px;">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
|
||||||
</div>
|
|
||||||
<div v-if="study.StudyName" style="text-overflow: ellipsis;overflow: hidden;">
|
|
||||||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="taskInfo && !taskInfo.IsShowStudyName">
|
|
||||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
|
||||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
|
||||||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div v-else>
|
|
||||||
<!-- 关键序列 -->
|
|
||||||
{{ $t('trials:reading:title:keySeries') }}
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<div class="dicom-list-container">
|
|
||||||
<div
|
|
||||||
v-for="(series, i) in study.SeriesList"
|
|
||||||
:key="series.Id"
|
|
||||||
style="position:relative;margin-top:1px;"
|
|
||||||
@click="activeSeries(series, i, index)"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
:class="{'series-active': index === activeStudyIndex && i === activeSeriesIndex}"
|
|
||||||
class="series-wrapper"
|
|
||||||
>
|
|
||||||
<div class="series-image">
|
|
||||||
<el-image
|
|
||||||
style="width: 100%;height: 100%;"
|
|
||||||
:src="`${OSSclientConfig.basePath}${series.ImageResizePath}`"
|
|
||||||
fit="fill"
|
|
||||||
crossorigin="anonymous"
|
|
||||||
/>
|
|
||||||
</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 }}
|
|
||||||
</div>
|
|
||||||
<div v-if="series.SliceThickness && !study.IsCriticalSequence" class="text-desc">
|
|
||||||
T: {{ parseFloat(series.SliceThickness).toFixed(digitPlaces) }}
|
|
||||||
</div>
|
|
||||||
<div class="text-desc">
|
|
||||||
<span v-show="series.LoadedImageCount < series.InstanceCount">
|
|
||||||
{{ series.Modality }}: {{ series.LoadedImageCount }}/{{ series.InstanceCount }} image
|
|
||||||
</span>
|
|
||||||
<span v-show="series.LoadedImageCount >= series.InstanceCount">{{ series.Modality }}: {{ series.InstanceCount }} image</span>
|
|
||||||
</div>
|
|
||||||
<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.LoadedImageCount > 0 && series.LoadedImageCount < series.InstanceCount" style="width: 100%;">
|
|
||||||
<el-progress
|
|
||||||
:percentage="parseInt((series.LoadedImageProgress / series.InstanceCount).toFixed(2))"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-collapse-item>
|
|
||||||
</el-collapse>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'StudyList',
|
|
||||||
props: {
|
|
||||||
visitTaskInfo: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
markedSeriesIds: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
loading: false,
|
|
||||||
activeNames: [],
|
|
||||||
activeStudyIndex: -1,
|
|
||||||
activeSeriesIndex: -1,
|
|
||||||
taskInfo: null,
|
|
||||||
studyList: [],
|
|
||||||
annotations: [],
|
|
||||||
digitPlaces: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
|
||||||
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
|
||||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
|
||||||
this.studyList = this.visitTaskInfo.StudyList
|
|
||||||
this.annotations = this.visitTaskInfo.Annotations
|
|
||||||
if (this.studyList.length === 0) return
|
|
||||||
this.$nextTick(() => {
|
|
||||||
this.activeStudy(this.studyList[0].StudyId)
|
|
||||||
})
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
activeSeries(series, seriesIndex, studyIndex) {
|
|
||||||
this.activeStudyIndex = studyIndex
|
|
||||||
this.activeSeriesIndex = seriesIndex
|
|
||||||
this.$emit('activeSeries', series)
|
|
||||||
},
|
|
||||||
activeStudy(id) {
|
|
||||||
if (this.activeNames.indexOf(id) > -1) return
|
|
||||||
this.activeNames.push(id)
|
|
||||||
},
|
|
||||||
setSeriesActive(studyIndex, seriesIndex) {
|
|
||||||
this.activeStudyIndex = studyIndex
|
|
||||||
this.activeSeriesIndex = seriesIndex
|
|
||||||
const studyId = this.studyList[studyIndex].StudyId
|
|
||||||
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)
|
|
||||||
if (i === -1) return
|
|
||||||
let newIndex = null
|
|
||||||
if (type === -1) {
|
|
||||||
newIndex = i === 0 ? i : i - 1
|
|
||||||
} else {
|
|
||||||
newIndex = i >= seriseList.length - 1 ? i : i + 1
|
|
||||||
}
|
|
||||||
const studyIndex = seriseList[newIndex].StudyIndex
|
|
||||||
const seriesIndex = seriseList[newIndex].SeriesIndex
|
|
||||||
this.setSeriesActive(studyIndex, seriesIndex)
|
|
||||||
this.activeSeries(seriseList[newIndex], seriesIndex, studyIndex)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.study-wrapper{
|
|
||||||
width:100%;
|
|
||||||
height: 100%;
|
|
||||||
overflow-y: hidden;
|
|
||||||
overflow-x: hidden;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
.study-info {
|
|
||||||
font-size: 16px;
|
|
||||||
font-weight: bold;
|
|
||||||
color: #ddd;
|
|
||||||
padding: 5px 0px;
|
|
||||||
margin: 0;
|
|
||||||
text-align: center;
|
|
||||||
background-color: #4c4c4c;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
.dicom-desc{
|
|
||||||
font-weight: bold;
|
|
||||||
font-size: 13px;
|
|
||||||
text-align: left;
|
|
||||||
color: #d0d0d0;
|
|
||||||
padding: 2px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
}
|
|
||||||
|
|
||||||
.ps {
|
|
||||||
flex: 1;
|
|
||||||
overflow-anchor: none;
|
|
||||||
touch-action: auto;
|
|
||||||
overflow-y: auto;
|
|
||||||
}
|
|
||||||
.series-active {
|
|
||||||
background-color: #607d8b!important;
|
|
||||||
border: 1px solid #607d8b!important;
|
|
||||||
}
|
|
||||||
::v-deep.el-progress__text{
|
|
||||||
color: #ccc;
|
|
||||||
font-size: 12px;
|
|
||||||
}
|
|
||||||
.dicom-list-container{
|
|
||||||
width: 100%;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
justify-content: flex-start;
|
|
||||||
.series-wrapper {
|
|
||||||
width: 100%;
|
|
||||||
padding: 5px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
align-items: center;
|
|
||||||
cursor: pointer;
|
|
||||||
background-color: #3a3a3a;
|
|
||||||
.el-progress__text{
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.el-progress-bar{
|
|
||||||
padding-right:0px;
|
|
||||||
}
|
|
||||||
.series-image {
|
|
||||||
width: 50px;
|
|
||||||
height: 50px;
|
|
||||||
}
|
|
||||||
.series-text {
|
|
||||||
flex: 1;
|
|
||||||
padding-left: 5px;
|
|
||||||
color: #ddd;
|
|
||||||
position: relative;
|
|
||||||
.text-desc {
|
|
||||||
width: 100px;
|
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
font-size: 12px;
|
|
||||||
line-height: 16px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::v-deep.el-collapse{
|
|
||||||
border: none;
|
|
||||||
.el-collapse-item{
|
|
||||||
background-color: #000!important;
|
|
||||||
color: #ddd;
|
|
||||||
|
|
||||||
}
|
|
||||||
.el-collapse-item__content{
|
|
||||||
padding-bottom:0px;
|
|
||||||
background-color: #000!important;
|
|
||||||
}
|
|
||||||
.el-collapse-item__header{
|
|
||||||
background-color: #000!important;
|
|
||||||
color: #ddd;
|
|
||||||
border-bottom-color:#5a5a5a;
|
|
||||||
padding-left: 5px;
|
|
||||||
// height: 50px;
|
|
||||||
line-height: 20px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
::v-deep .el-progress-bar__inner{
|
|
||||||
transition: width 0s ease;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,670 +0,0 @@
|
||||||
<template>
|
|
||||||
<div
|
|
||||||
ref="viewport"
|
|
||||||
class="viewport-wrapper"
|
|
||||||
@mouseup="sliderMouseup"
|
|
||||||
@mousemove="sliderMousemove"
|
|
||||||
@mouseleave="sliderMouseleave"
|
|
||||||
>
|
|
||||||
<div v-if="series && taskInfo" class="left-top-text">
|
|
||||||
<div
|
|
||||||
v-if="taskInfo.IsExistsClinicalData"
|
|
||||||
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"
|
|
||||||
class="subject-info"
|
|
||||||
>
|
|
||||||
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
|
|
||||||
</h2>
|
|
||||||
<div>Series: #{{ series.SeriesNumber }}</div>
|
|
||||||
<div v-if="series.Stack">Image: #{{ `${series.SliceIndex + 1}/${series.Stack.length}` }}</div>
|
|
||||||
<div>{{ series.Modality }}</div>
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
v-if="series && taskInfo && taskInfo.IsReadingTaskViewInOrder === 1"
|
|
||||||
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" class="right-top-text">
|
|
||||||
<div>{{ series.Description }}</div>
|
|
||||||
</div>
|
|
||||||
<div v-if="series" class="left-bottom-text">
|
|
||||||
<div v-show="mousePosition.index.length > 0">
|
|
||||||
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)">
|
|
||||||
{{mousePosition.modalityUnit}}: {{ digitPlaces === -1 ?mousePosition.value.toFixed(3) :mousePosition.value.toFixed(digitPlaces) }}
|
|
||||||
</div>
|
|
||||||
<div v-else-if="mousePosition.value">
|
|
||||||
Density: {{ mousePosition.value }}
|
|
||||||
</div>
|
|
||||||
<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>
|
|
||||||
<div v-show="series.SliceThickness">Slice Thickness: {{ `${Number(series.SliceThickness).toFixed(digitPlaces)} mm` }}</div>
|
|
||||||
<div v-show="imageInfo.wwwc ">WW/WL: {{ imageInfo.wwwc }}</div>
|
|
||||||
</div>
|
|
||||||
<div class="orientation-top">
|
|
||||||
{{ markers.top }}
|
|
||||||
</div>
|
|
||||||
<div class="orientation-right">
|
|
||||||
{{ markers.right }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="orientation-bottom">
|
|
||||||
{{ markers.bottom }}
|
|
||||||
</div>
|
|
||||||
<div class="orientation-left">
|
|
||||||
{{ markers.left }}
|
|
||||||
</div>
|
|
||||||
<div ref="sliderBox" class="right-slider-box" @click.stop="clickSlider($event)">
|
|
||||||
<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,
|
|
||||||
// eventTarget,
|
|
||||||
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',
|
|
||||||
props: {
|
|
||||||
renderingEngineId: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
viewportId: {
|
|
||||||
type: String,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
viewportIndex: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
element: '',
|
|
||||||
series: null,
|
|
||||||
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
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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']
|
|
||||||
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_STACK_NEW_IMAGE', this.stackNewImage)
|
|
||||||
// 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)
|
|
||||||
},
|
|
||||||
stackNewImage(e) {
|
|
||||||
const { detail } = e
|
|
||||||
this.series.SliceIndex = detail.imageIdIndex
|
|
||||||
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()
|
|
||||||
this.imageInfo.zoom = zoom.toFixed(4)
|
|
||||||
this.imageInfo.size = `${detail.image.columns}*${detail.image.rows}`
|
|
||||||
const imagePlaneModule = metaData.get('imagePlaneModule', detail.imageId)
|
|
||||||
this.imageInfo.location = imagePlaneModule.sliceLocation
|
|
||||||
// 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)
|
|
||||||
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)
|
|
||||||
},
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
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) {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cornerstoneToolsMouseMove(e) {
|
|
||||||
const { currentPoints } = e.detail
|
|
||||||
const worldPoint = currentPoints.world
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
|
||||||
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)
|
|
||||||
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
|
|
||||||
},
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,101 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="visit-review-container">
|
|
||||||
<el-tabs v-model="activeName">
|
|
||||||
<!-- 阅片 -->
|
|
||||||
<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
|
|
||||||
v-if="taskInfo && !taskInfo.IseCRFShowInDicomReading"
|
|
||||||
:label="$t('trials:reading:tabTitle:report')"
|
|
||||||
name="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>
|
|
||||||
</el-tabs>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import ReadPage from './ReadPage'
|
|
||||||
import ReportPage from './ReportPage'
|
|
||||||
import CustomizeReportPage from './customize/ReportPage'
|
|
||||||
export default {
|
|
||||||
name: 'VisitReview',
|
|
||||||
components: {
|
|
||||||
ReadPage,
|
|
||||||
ReportPage,
|
|
||||||
CustomizeReportPage
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
readingTool: {
|
|
||||||
type: Number,
|
|
||||||
default: 0
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
activeName: 'read',
|
|
||||||
taskInfo: null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
console.log(this.readingTool)
|
|
||||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
setReadingTaskState(state) {
|
|
||||||
this.$refs['readPage'].setReadingTaskState(state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.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;
|
|
||||||
|
|
||||||
.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>
|
|
||||||
|
|
@ -1,325 +0,0 @@
|
||||||
<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>
|
|
||||||
|
|
@ -1,438 +0,0 @@
|
||||||
<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>
|
|
||||||
|
|
@ -1,855 +0,0 @@
|
||||||
<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>
|
|
||||||
|
|
@ -1,324 +0,0 @@
|
||||||
<template>
|
|
||||||
<div>
|
|
||||||
<div
|
|
||||||
v-if="!!question.GroupName && question.Type==='group'"
|
|
||||||
>
|
|
||||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
|
||||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
|
||||||
</h4>
|
|
||||||
</div>
|
|
||||||
<template v-else>
|
|
||||||
<el-form-item
|
|
||||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
|
|
||||||
:label="`${question.QuestionName}`"
|
|
||||||
:prop="question.Id"
|
|
||||||
:rules="[
|
|
||||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
|
||||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
|
||||||
]"
|
|
||||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
|
||||||
>
|
|
||||||
|
|
||||||
<!-- 输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-if="question.Type==='input'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
/>
|
|
||||||
<!-- 多行文本输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-else-if="question.Type==='textarea'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
|
||||||
maxlength="500"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
/>
|
|
||||||
<!-- 下拉框 -->
|
|
||||||
<el-select
|
|
||||||
v-else-if="question.Type==='select'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode)"
|
|
||||||
clearable
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
>
|
|
||||||
<template v-if="question.TableQuestionType === 1">
|
|
||||||
<el-option
|
|
||||||
v-for="item in organList"
|
|
||||||
:key="item.Id"
|
|
||||||
:label="item[question.DataTableColumn]"
|
|
||||||
:value="item[question.DataTableColumn]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[question.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[question.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="val in question.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
:value="val"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-select>
|
|
||||||
<!-- 单选 -->
|
|
||||||
<el-radio-group
|
|
||||||
v-else-if="question.Type==='radio'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
@change="((val)=>{formItemChange(val, question)})"
|
|
||||||
>
|
|
||||||
<template v-if="question.DictionaryCode">
|
|
||||||
<el-radio
|
|
||||||
v-for="item of $d[question.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:label="String(item.value)"
|
|
||||||
>
|
|
||||||
{{ item.label }}
|
|
||||||
</el-radio>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="question.TypeValue">
|
|
||||||
<el-radio
|
|
||||||
v-for="val in question.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
>
|
|
||||||
{{ val }}
|
|
||||||
</el-radio>
|
|
||||||
</template>
|
|
||||||
</el-radio-group>
|
|
||||||
<!-- 复选框 -->
|
|
||||||
<el-checkbox-group
|
|
||||||
v-else-if="question.Type==='checkbox'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-for="val in question.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
>
|
|
||||||
{{ val }}
|
|
||||||
</el-checkbox>
|
|
||||||
</el-checkbox-group>
|
|
||||||
<!-- 数值 -->
|
|
||||||
<template v-else-if="question.Type==='number'">
|
|
||||||
<el-input-number
|
|
||||||
v-if="question.ValueType === 0"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:precision="0"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
/>
|
|
||||||
<el-input-number
|
|
||||||
v-else-if="question.ValueType === 3"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
/>
|
|
||||||
<el-input-number
|
|
||||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
:precision="digitPlaces"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<el-input
|
|
||||||
v-else-if="question.Type==='calculation'"
|
|
||||||
v-model="questionForm[question.Id]"
|
|
||||||
disabled
|
|
||||||
>
|
|
||||||
<template v-if="question.Unit" slot="append">
|
|
||||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
<!-- 上传图像 -->
|
|
||||||
<el-upload
|
|
||||||
v-else-if="question.Type==='upload'"
|
|
||||||
action
|
|
||||||
:accept="accept"
|
|
||||||
:limit="question.ImageCount"
|
|
||||||
:on-preview="handlePictureCardPreview"
|
|
||||||
:before-upload="handleBeforeUpload"
|
|
||||||
:http-request="uploadScreenshot"
|
|
||||||
list-type="picture-card"
|
|
||||||
:on-remove="handleRemove"
|
|
||||||
:file-list="fileList"
|
|
||||||
:class="{disabled:fileList.length >= question.ImageCount}"
|
|
||||||
:disabled="readingTaskState >= 2"
|
|
||||||
>
|
|
||||||
<i slot="default" class="el-icon-plus" />
|
|
||||||
<div slot="file" slot-scope="{file}">
|
|
||||||
<img
|
|
||||||
class="el-upload-list__item-thumbnail"
|
|
||||||
:src="OSSclientConfig.basePath + file.url"
|
|
||||||
alt=""
|
|
||||||
>
|
|
||||||
<span class="el-upload-list__item-actions">
|
|
||||||
<span
|
|
||||||
class="el-upload-list__item-preview"
|
|
||||||
@click="handlePictureCardPreview(file)"
|
|
||||||
>
|
|
||||||
<i class="el-icon-zoom-in" />
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<span
|
|
||||||
v-if="readingTaskState < 2"
|
|
||||||
class="el-upload-list__item-delete"
|
|
||||||
@click="handleRemove(file)"
|
|
||||||
>
|
|
||||||
<i class="el-icon-delete" />
|
|
||||||
</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
|
||||||
<el-dialog
|
|
||||||
v-if="question.Type==='upload'"
|
|
||||||
append-to-body
|
|
||||||
:visible.sync="imgVisible"
|
|
||||||
width="600px"
|
|
||||||
>
|
|
||||||
<el-image :src="imageUrl" width="100%">
|
|
||||||
<div slot="placeholder" class="image-slot">
|
|
||||||
加载中<span class="dot">...</span>
|
|
||||||
</div>
|
|
||||||
</el-image>
|
|
||||||
</el-dialog>
|
|
||||||
</el-form-item>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<question-form-item
|
|
||||||
v-for="(item) in question.Childrens"
|
|
||||||
:key="item.Id"
|
|
||||||
:question="item"
|
|
||||||
:question-form="questionForm"
|
|
||||||
:reading-task-state="readingTaskState"
|
|
||||||
:visitTaskId="visitTaskId"
|
|
||||||
@resetFormItemData="resetFormItemData"
|
|
||||||
@setFormItemData="setFormItemData"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
// import { uploadReadingAnswerImage } from '@/api/trials'
|
|
||||||
import { mapGetters } from 'vuex'
|
|
||||||
export default {
|
|
||||||
name: 'QuestionFormItem',
|
|
||||||
props: {
|
|
||||||
questionForm: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
question: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readingTaskState: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
visitTaskId: {
|
|
||||||
type: String,
|
|
||||||
default: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
fileList: [],
|
|
||||||
accept: '.png,.jpg,.jpeg',
|
|
||||||
imgVisible: false,
|
|
||||||
imageUrl: '',
|
|
||||||
urls: [],
|
|
||||||
digitPlaces: 2
|
|
||||||
}
|
|
||||||
},
|
|
||||||
computed: {
|
|
||||||
...mapGetters(['language'])
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
questionForm: {
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
handler(v) {
|
|
||||||
// console.log(v)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
|
||||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
formItemChange(v, question) {
|
|
||||||
if (question.Childrens.length > 0) {
|
|
||||||
this.resetChild(question.Childrens)
|
|
||||||
} else {
|
|
||||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
|
||||||
}
|
|
||||||
},
|
|
||||||
resetChild(obj) {
|
|
||||||
obj.forEach(i => {
|
|
||||||
this.$emit('resetFormItemData', i.Id)
|
|
||||||
if (i.Childrens && i.Childrens.length > 0) {
|
|
||||||
this.resetChild(i.Childrens)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
},
|
|
||||||
resetFormItemData(v) {
|
|
||||||
this.$emit('resetFormItemData', v)
|
|
||||||
},
|
|
||||||
setFormItemData(obj) {
|
|
||||||
this.$emit('setFormItemData', obj)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.mb{
|
|
||||||
margin-bottom: 0px;
|
|
||||||
}
|
|
||||||
.disabled{
|
|
||||||
::v-deep .el-upload--picture-card {
|
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.uploadWrapper{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column !important;
|
|
||||||
align-items: flex-start;
|
|
||||||
}
|
|
||||||
::v-deep .el-input.is-disabled .el-input__inner{
|
|
||||||
background-color: #646464a1;
|
|
||||||
}
|
|
||||||
::v-deep .el-input-group__append, .el-input-group__prepend{
|
|
||||||
padding: 0 10px;
|
|
||||||
}
|
|
||||||
::v-deep .el-form-item__content {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
::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>
|
|
||||||
|
|
@ -1,365 +0,0 @@
|
||||||
<template>
|
|
||||||
<div class="table-question-form">
|
|
||||||
<div style="display: flex;justify-content: space-between;">
|
|
||||||
<h3 v-if="qsForm.LesionName" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
|
||||||
{{ qsForm.LesionName }}
|
|
||||||
</h3>
|
|
||||||
<!-- 关闭 -->
|
|
||||||
<div>
|
|
||||||
<i class="el-icon-circle-close" style="font-size: 25px;cursor: pointer;" @click="close" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<el-form-item
|
|
||||||
:label="$t('trials:reading:title:lesionType')"
|
|
||||||
prop="LesionType"
|
|
||||||
:rules="[
|
|
||||||
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['blur']},
|
|
||||||
]"
|
|
||||||
>
|
|
||||||
<!-- 下拉框 -->
|
|
||||||
<el-select
|
|
||||||
v-model="qsForm.LesionType"
|
|
||||||
filterable
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2 || !isBaseLineTask"
|
|
||||||
@change="((val)=>{lesionTypeChange(val)})"
|
|
||||||
>
|
|
||||||
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d.LesionType"
|
|
||||||
v-show="!(isBaseLineTask && item.value === 2)"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
|
|
||||||
</el-select>
|
|
||||||
</el-form-item>
|
|
||||||
<!-- 靶病灶、非靶病灶的器官为肝脏/Liver时,需要选择典型肝内病灶。该值默认为否;如果选择是,对于靶病灶需要提示“按照《独立影像评估章程》的相关规则,对于典型肝内靶病灶请测量肿瘤活性部分最长径。”,提示方式为在“长径”属性上,显示浮框或者增加!
|
|
||||||
-->
|
|
||||||
<el-form-item
|
|
||||||
v-for="qs in questions"
|
|
||||||
v-show="qs.ShowQuestion!==2"
|
|
||||||
:key="qs.Id"
|
|
||||||
:prop="qs.Id"
|
|
||||||
: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.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'">
|
|
||||||
|
|
||||||
<el-input
|
|
||||||
v-if="qs.Type==='input' || qs.Type==='number'"
|
|
||||||
v-model="qsForm[qs.Id]"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName))"
|
|
||||||
@change="((val)=>{formItemChange(val, qs)})"
|
|
||||||
>
|
|
||||||
<template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append">
|
|
||||||
{{ $fd('ValueUnit', parseInt(qs.Unit)) }}
|
|
||||||
</template>
|
|
||||||
</el-input>
|
|
||||||
</template>
|
|
||||||
<!-- 多行文本输入框 -->
|
|
||||||
<el-input
|
|
||||||
v-if="qs.Type==='textarea'"
|
|
||||||
v-model="qsForm[qs.Id]"
|
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 2, maxRows: 4}"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
|
||||||
@change="((val)=>{formItemChange(val, qs)})"
|
|
||||||
/>
|
|
||||||
<!-- 下拉框 -->
|
|
||||||
<el-select
|
|
||||||
v-if="qs.Type==='select'"
|
|
||||||
v-model="qsForm[qs.Id]"
|
|
||||||
filterable
|
|
||||||
:placeholder="qs.QuestionMark === 8 ? $t('common:placeholder:selectorsearch') : qs.QuestionMark === 2 ? '' : $t('common:placeholder:select')"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False'|| !!answer.SplitOrMergeLesionName)) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName)) || (qs.QuestionMark === 21 && (isCurrentTaskAdd === 'False'|| !!answer.SplitOrMergeLesionName)) || (questionForm.LesionOrgan && questionForm.LesionOrgan !== '肝脏' && questionForm.LesionOrgan !== 'Liver' && qs.QuestionMark === 21)"
|
|
||||||
@change="((val)=>{formItemChange(val, qs)})"
|
|
||||||
>
|
|
||||||
<template v-if="qs.QuestionMark === 8" #prefix>
|
|
||||||
<span style="padding-left: 5px;">
|
|
||||||
<i class="el-icon-search" />
|
|
||||||
</span>
|
|
||||||
</template>
|
|
||||||
<template v-if="qs.TableQuestionType === 1">
|
|
||||||
<el-option
|
|
||||||
v-for="item in organList"
|
|
||||||
:key="item.Id"
|
|
||||||
:label="item[qs.DataTableColumn]"
|
|
||||||
:value="item[qs.DataTableColumn]"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && isBaseLineTask">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
v-show="(lesionType === 0 && item.value ===0) || (lesionType === 1 && (item.value ===0))"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask">
|
|
||||||
<el-option-group
|
|
||||||
:label="!isNaN(parseFloat(answer.LastTaskState)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(qs.DictionaryCode,parseFloat(answer.LastTaskState))}` : ''"
|
|
||||||
>
|
|
||||||
<!-- 首次分裂的病灶只能选择存在 -->
|
|
||||||
<template v-if="answer.IsFristAdd=== 'True' && answer.SplitOrMergeType === '0'">
|
|
||||||
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
v-show="item.value === 0"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<!-- 首次添加的新病灶不能为无法评估和消失 -->
|
|
||||||
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
v-show="item.value === 0 || item.value === 1"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="item of filterState($d[qs.DictionaryCode])"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
</el-option-group>
|
|
||||||
</template>
|
|
||||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d[qs.DictionaryCode]"
|
|
||||||
:key="item.id"
|
|
||||||
:value="item.value"
|
|
||||||
:label="item.label"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
<template v-else>
|
|
||||||
<el-option
|
|
||||||
v-for="val in qs.TypeValue.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
:value="val"
|
|
||||||
/>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
</el-select>
|
|
||||||
<!-- 单选 -->
|
|
||||||
<el-radio-group
|
|
||||||
v-if="qs.Type==='radio'"
|
|
||||||
v-model="qsForm[qs.id]"
|
|
||||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
|
||||||
>
|
|
||||||
<el-radio
|
|
||||||
v-for="val in qs.options.split('|')"
|
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
>
|
|
||||||
{{ val }}
|
|
||||||
</el-radio>
|
|
||||||
</el-radio-group>
|
|
||||||
</el-form-item>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: 'TableQuestionFormItem',
|
|
||||||
props: {
|
|
||||||
tableInfo: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
answer: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
questionForm: {
|
|
||||||
type: Object,
|
|
||||||
default() {
|
|
||||||
return {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
organs: {
|
|
||||||
type: Array,
|
|
||||||
default() {
|
|
||||||
return []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
readingTaskState: {
|
|
||||||
type: Number,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isBaseLineTask: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
},
|
|
||||||
isCurrentTask: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true
|
|
||||||
}
|
|
||||||
},
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
isCurrentTaskAdd: null,
|
|
||||||
lesionType: null,
|
|
||||||
questions: [],
|
|
||||||
organList: [],
|
|
||||||
qsForm: {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
watch: {
|
|
||||||
questionForm: {
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
handler(v) {
|
|
||||||
if (v.MeasureData) {
|
|
||||||
const { markTool } = v.MeasureData
|
|
||||||
if (markTool === 'Bidirectional') {
|
|
||||||
this.getOrganList(1)
|
|
||||||
} else if (markTool === 'Length') {
|
|
||||||
this.getOrganList(0)
|
|
||||||
} else {
|
|
||||||
this.getOrganList()
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
this.getOrganList()
|
|
||||||
}
|
|
||||||
for (const key in v) {
|
|
||||||
this.$set(this.qsForm, key, v[key])
|
|
||||||
}
|
|
||||||
this.isCurrentTaskAdd = v.IsCurrentTaskAdd
|
|
||||||
}
|
|
||||||
},
|
|
||||||
tableInfo: {
|
|
||||||
deep: true,
|
|
||||||
immediate: true,
|
|
||||||
handler(v) {
|
|
||||||
if (v) {
|
|
||||||
this.lesionType = v.LesionType
|
|
||||||
this.questions = v.TableQuestions.Questions
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
lesionTypeChange(v) {
|
|
||||||
this.$emit('lesionTypeChange', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, newLesionType: v })
|
|
||||||
},
|
|
||||||
formItemChange(v, qs) {
|
|
||||||
const updateArr = []
|
|
||||||
if (qs.QuestionMark === 8 && qs.RelationQuestions.length > 0) {
|
|
||||||
// 当选择部位时,联动器官、位置、是否淋巴结问题答案
|
|
||||||
const index = this.organList.findIndex(item => item[qs.DataTableColumn] === v)
|
|
||||||
if (index > -1) {
|
|
||||||
const selected = this.organList[index]
|
|
||||||
qs.RelationQuestions.map(q => {
|
|
||||||
const val = selected[q.DataTableColumn]
|
|
||||||
updateArr.push({ questionId: q.Id, val: val, questionMark: q.QuestionMark })
|
|
||||||
})
|
|
||||||
updateArr.push({ questionId: 'OrganInfoId', val: selected.OrganInfoId })
|
|
||||||
updateArr.push({ questionId: 'IsCanEditPosition', val: selected.IsCanEditPosition })
|
|
||||||
} else {
|
|
||||||
qs.RelationQuestions.map(q => {
|
|
||||||
updateArr.push({ questionId: q.Id, val: '', questionMark: q.QuestionMark })
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.$emit('update', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, questionMark: qs.QuestionMark, questionId: qs.Id, val: v, updateArr })
|
|
||||||
},
|
|
||||||
getOrganList(isLymphNodes = null) {
|
|
||||||
const idx = this.organs.findIndex(i => i.LesionType === this.questionForm.LesionType)
|
|
||||||
if (idx > -1) {
|
|
||||||
const arr = this.organs[idx].OrganList
|
|
||||||
|
|
||||||
if (!isNaN(parseInt(isLymphNodes))) {
|
|
||||||
this.organList = arr.filter((item) => item.IsLymphNodes === parseInt(isLymphNodes))
|
|
||||||
} else {
|
|
||||||
this.organList = arr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
filterState(arr) {
|
|
||||||
if (!this.isBaseLineTask) {
|
|
||||||
const isLymphLesion = this.questionForm.IsLymphNodes
|
|
||||||
const lesionLength = this.questionForm.LesionLength
|
|
||||||
const lesionShort = this.questionForm.LesionShort
|
|
||||||
const bLesionL = !isNaN(parseFloat(this.questionForm.BaseLineMajorAxis)) ? parseFloat(this.questionForm.BaseLineMajorAxis) : 0
|
|
||||||
const bLesionS = !isNaN(parseFloat(this.questionForm.BaseLineShortAxis)) ? parseFloat(this.questionForm.BaseLineShortAxis) : 0
|
|
||||||
if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort < bLesionS) {
|
|
||||||
arr = arr.filter(i => i.value !== 1)
|
|
||||||
} else if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort >= 10 && lesionShort > bLesionS) {
|
|
||||||
arr = arr.filter(i => i.value === 0 || i.value === 1)
|
|
||||||
} else if (this.lesionType === 1 && isLymphLesion === 0 && this.questionForm.MeasureData && (this.questionForm.MeasureData.markTool === 'Length' || this.questionForm.MeasureData.markTool === 'Bidirectional') && lesionLength < bLesionL) {
|
|
||||||
arr = arr.filter(i => i.value !== 1)
|
|
||||||
}
|
|
||||||
return arr
|
|
||||||
} else {
|
|
||||||
return arr
|
|
||||||
}
|
|
||||||
},
|
|
||||||
close() {
|
|
||||||
this.$emit('close', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.table-question-form{
|
|
||||||
::v-deep .el-form-item__label{
|
|
||||||
color: #c3c3c3;
|
|
||||||
}
|
|
||||||
::v-deep .el-input .el-input__inner{
|
|
||||||
background-color: transparent;
|
|
||||||
color: #ddd;
|
|
||||||
border: 1px solid #5e5e5e;
|
|
||||||
}
|
|
||||||
::v-deep .el-form-item{
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
justify-content: flex-start;
|
|
||||||
}
|
|
||||||
::v-deep .el-form-item__content{
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
::v-deep .el-input.is-disabled .el-input__inner{
|
|
||||||
background-color: #646464a1;
|
|
||||||
}
|
|
||||||
::v-deep .el-select.is-disabled .el-input__inner{
|
|
||||||
background-color: #646464a1;
|
|
||||||
}
|
|
||||||
::v-deep .el-button--mini, .el-button--mini.is-round {
|
|
||||||
padding: 7px 10px;
|
|
||||||
}
|
|
||||||
.el-form-item__content
|
|
||||||
.el-select{
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
.input-width1{
|
|
||||||
width: calc(100% - 60px)!important;
|
|
||||||
}
|
|
||||||
.input-width2{
|
|
||||||
width: 100% !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
|
||||||
|
|
@ -1,283 +0,0 @@
|
||||||
const config = {
|
|
||||||
'standards': [
|
|
||||||
{
|
|
||||||
'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': 'rectangle',
|
|
||||||
'toolName': 'RectangleROI',
|
|
||||||
'i18nKey': 'trials:reading:button:rectangle',
|
|
||||||
'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': ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'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': ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'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': 'rectangle',
|
|
||||||
'toolName': 'RectangleROI',
|
|
||||||
'i18nKey': 'trials:reading:button:rectangle',
|
|
||||||
'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': ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'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': ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'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': ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'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': 'arrow',
|
|
||||||
'toolName': 'ArrowAnnotate',
|
|
||||||
'i18nKey': 'trials:reading:button:arrowAnnotate',
|
|
||||||
'isDisabled': false,
|
|
||||||
'disabledReason': ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
'type': 19,
|
|
||||||
'name': 'IVUS定量评估',
|
|
||||||
'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': ''
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'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 || []
|
|
||||||
}
|
|
||||||
const getCustomizeStandardsTools = (toolNames) => {
|
|
||||||
const filteredTools = config.customizeStandards.filter(item => toolNames.includes(item.toolName))
|
|
||||||
return filteredTools || []
|
|
||||||
}
|
|
||||||
export { config, getTools, getCustomizeStandardsTools }
|
|
||||||
|
|
@ -1,305 +0,0 @@
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
@ -1,113 +0,0 @@
|
||||||
<template>
|
|
||||||
<div v-loading="loading" class="reading-viewer-container">
|
|
||||||
<!-- 访视阅片 -->
|
|
||||||
<visit-review
|
|
||||||
v-if="taskInfo && taskInfo.ReadingCategory=== 1"
|
|
||||||
/>
|
|
||||||
<!-- 临床数据 -->
|
|
||||||
<el-dialog
|
|
||||||
:visible.sync="clinicalDataVisible"
|
|
||||||
:custom-class="isClinicalDataFullscreen?'full-dialog-container':'dialog-container'"
|
|
||||||
:show-close="false"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
:fullscreen="isClinicalDataFullscreen"
|
|
||||||
>
|
|
||||||
<span slot="title" class="dialog-footer">
|
|
||||||
<!-- 当前阅片任务存在临床数据,请查看。若已查看,请点击“确认” -->
|
|
||||||
<span v-if="!closeCDVisible">{{ $t('trials:reading:dagTitle:msg1') }}</span>
|
|
||||||
<div style="position: absolute;right: 20px;top: 10px;">
|
|
||||||
<svg-icon :icon-class="isClinicalDataFullscreen?'exit-fullscreen':'fullscreen'" style="cursor: pointer;font-size: 20px;" @click="isClinicalDataFullscreen=!isClinicalDataFullscreen" />
|
|
||||||
<svg-icon v-if="closeCDVisible" icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="clinicalDataVisible = false" />
|
|
||||||
</div>
|
|
||||||
</span>
|
|
||||||
<div style="height: 100%;margin:0;display: flex;flex-direction: column;">
|
|
||||||
<clinical-data
|
|
||||||
v-if="clinicalDataVisible"
|
|
||||||
style="flex: 1"
|
|
||||||
:trial-id="trialId"
|
|
||||||
:subject-id="taskInfo.SubjectId"
|
|
||||||
:visit-task-id="cdVisitTaskId"
|
|
||||||
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
|
|
||||||
/>
|
|
||||||
<div v-if="!closeCDVisible" style="text-align:right">
|
|
||||||
<el-button type="primary" @click="handleConfirmCD">{{ $t('trials:reading:button:confirm') }}</el-button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</el-dialog>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<script>
|
|
||||||
import VisitReview from './components/VisitReview'
|
|
||||||
import ClinicalData from '@/views/trials/trials-panel/reading/clinical-data'
|
|
||||||
export default {
|
|
||||||
name:'Dicoms3d',
|
|
||||||
components: { VisitReview,ClinicalData },
|
|
||||||
data() {
|
|
||||||
return {
|
|
||||||
taskInfo: null,
|
|
||||||
trialId: '',
|
|
||||||
loading: false,
|
|
||||||
clinicalDataVisible: false,
|
|
||||||
isClinicalDataFullscreen: false,
|
|
||||||
closeCDVisible: false,
|
|
||||||
cdVisitTaskId: ''
|
|
||||||
}
|
|
||||||
},
|
|
||||||
mounted() {
|
|
||||||
this.trialId = this.$route.query.trialId
|
|
||||||
this.getTaskInfo()
|
|
||||||
},
|
|
||||||
methods: {
|
|
||||||
async getTaskInfo() {
|
|
||||||
this.loading = true
|
|
||||||
try {
|
|
||||||
const params = {
|
|
||||||
subjectId: this.$route.query.subjectId,
|
|
||||||
trialId: this.$route.query.trialId,
|
|
||||||
subjectCode: this.$route.query.subjectCode,
|
|
||||||
visitTaskId: this.$route.query.visitTaskId,
|
|
||||||
trialReadingCriterionId: this.$route.query.TrialReadingCriterionId
|
|
||||||
}
|
|
||||||
const res = await getNextTask(params)
|
|
||||||
this.taskInfo = res.Result
|
|
||||||
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
|
|
||||||
localStorage.setItem('digitPlaces', JSON.stringify(res.Result.DigitPlaces))
|
|
||||||
this.loading = false
|
|
||||||
this.$nextTick(() => {
|
|
||||||
if (this.taskInfo.IsExistsClinicalData && this.taskInfo.IsNeedReadClinicalData && !this.taskInfo.IsReadClinicalData) {
|
|
||||||
this.isClinicalDataFullscreen = false
|
|
||||||
this.clinicalDataVisible = true
|
|
||||||
this.cdVisitTaskId = this.taskInfo.VisitTaskId
|
|
||||||
}
|
|
||||||
})
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.reading-viewer-container {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
// ::v-deep .dialog-container{
|
|
||||||
// margin-top: 50px !important;
|
|
||||||
// width:75%;
|
|
||||||
// height:80%;
|
|
||||||
// }
|
|
||||||
// ::v-deep .el-dialog__body{
|
|
||||||
// padding: 10px;
|
|
||||||
// height: calc(100% - 70px);
|
|
||||||
// }
|
|
||||||
// .el-dialog__header{
|
|
||||||
// position: relative;
|
|
||||||
// }
|
|
||||||
// .full-dialog-container{
|
|
||||||
// ::v-deep .is-fullscreen .el-dialog__body{
|
|
||||||
// height: calc(100% - 70px);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
@ -302,7 +302,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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,9 +317,8 @@ export default {
|
||||||
},
|
},
|
||||||
handleSave(isPrompt = true) {
|
handleSave(isPrompt = true) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
let valid = await this.$refs['globalRuleForm'].validate()
|
||||||
let valid = await this.$refs['globalRuleForm'].validate()
|
if (valid) {
|
||||||
if (valid) {
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var visitTaskAnswerList = []
|
var visitTaskAnswerList = []
|
||||||
this.globalForm.taskList.forEach((item, index) => {
|
this.globalForm.taskList.forEach((item, index) => {
|
||||||
|
|
@ -348,23 +347,22 @@ export default {
|
||||||
trialId: this.globalInfo.trialId,
|
trialId: this.globalInfo.trialId,
|
||||||
visitTaskAnswerList
|
visitTaskAnswerList
|
||||||
}
|
}
|
||||||
await batchSubmitGlobalReadingInfo(params)
|
try {
|
||||||
this.loading = false
|
await batchSubmitGlobalReadingInfo(params)
|
||||||
if (isPrompt) {
|
this.loading = false
|
||||||
console.log(isPrompt)
|
if (isPrompt) {
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
console.log(isPrompt)
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
this.$emit('getGlInfo')
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
this.$emit('getGlInfo')
|
|
||||||
resolve(true)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
reject(false)
|
reject()
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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) {
|
handleSave(isPrompt = true) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
let valid = await this.$refs['globalRuleForm'].validate()
|
||||||
let valid = await this.$refs['globalRuleForm'].validate()
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var visitTaskAnswerList = []
|
var visitTaskAnswerList = []
|
||||||
this.globalForm.taskList.forEach((item, index) => {
|
this.globalForm.taskList.forEach((item, index) => {
|
||||||
|
|
@ -404,24 +404,22 @@ export default {
|
||||||
trialId: this.globalInfo.trialId,
|
trialId: this.globalInfo.trialId,
|
||||||
visitTaskAnswerList
|
visitTaskAnswerList
|
||||||
}
|
}
|
||||||
await batchSubmitGlobalReadingInfo(params)
|
try {
|
||||||
this.loading = false
|
await batchSubmitGlobalReadingInfo(params)
|
||||||
if (isPrompt) {
|
this.loading = false
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
if (isPrompt) {
|
||||||
|
console.log(isPrompt)
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
this.$emit('getGlInfo')
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
this.$emit('getGlInfo')
|
|
||||||
resolve(true)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resolve(false)
|
reject()
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getBeforeAnswer(qsId, row) {
|
getBeforeAnswer(qsId, row) {
|
||||||
|
|
|
||||||
|
|
@ -362,7 +362,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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,9 +377,8 @@ export default {
|
||||||
},
|
},
|
||||||
handleSave(isPrompt = true) {
|
handleSave(isPrompt = true) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
let valid = await this.$refs['globalRuleForm'].validate()
|
||||||
let valid = await this.$refs['globalRuleForm'].validate()
|
if (valid) {
|
||||||
if (valid) {
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var visitTaskAnswerList = []
|
var visitTaskAnswerList = []
|
||||||
this.globalForm.taskList.forEach((item, index) => {
|
this.globalForm.taskList.forEach((item, index) => {
|
||||||
|
|
@ -408,23 +407,22 @@ export default {
|
||||||
trialId: this.globalInfo.trialId,
|
trialId: this.globalInfo.trialId,
|
||||||
visitTaskAnswerList
|
visitTaskAnswerList
|
||||||
}
|
}
|
||||||
await batchSubmitGlobalReadingInfo(params)
|
try {
|
||||||
this.loading = false
|
await batchSubmitGlobalReadingInfo(params)
|
||||||
if (isPrompt) {
|
this.loading = false
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
if (isPrompt) {
|
||||||
|
console.log(isPrompt)
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
this.$emit('getGlInfo')
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
this.$emit('getGlInfo')
|
|
||||||
resolve(true)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resolve(false)
|
reject()
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,481 +0,0 @@
|
||||||
<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,9 +220,8 @@ export default {
|
||||||
},
|
},
|
||||||
handleSave(isPrompt = true) {
|
handleSave(isPrompt = true) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
let valid = await this.$refs['globalRuleForm'].validate()
|
||||||
let valid = await this.$refs['globalRuleForm'].validate()
|
if (valid) {
|
||||||
if (valid) {
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var visitTaskAnswerList = []
|
var visitTaskAnswerList = []
|
||||||
this.globalForm.taskList.forEach((item, index) => {
|
this.globalForm.taskList.forEach((item, index) => {
|
||||||
|
|
@ -248,24 +247,21 @@ export default {
|
||||||
trialId: this.globalInfo.trialId,
|
trialId: this.globalInfo.trialId,
|
||||||
visitTaskAnswerList
|
visitTaskAnswerList
|
||||||
}
|
}
|
||||||
await batchSubmitGlobalReadingInfo(params)
|
try {
|
||||||
this.loading = false
|
await batchSubmitGlobalReadingInfo(params)
|
||||||
if (isPrompt) {
|
this.loading = false
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
if (isPrompt) {
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
this.$emit('getGlInfo')
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
this.$emit('getGlInfo')
|
|
||||||
resolve(true)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resolve(false)
|
reject()
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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,10 +369,9 @@ export default {
|
||||||
return lesion ? lesion.Count : 0
|
return lesion ? lesion.Count : 0
|
||||||
},
|
},
|
||||||
handleSave(isPrompt = true) {
|
handleSave(isPrompt = true) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async(resolve, reject) => {
|
||||||
try {
|
let valid = await this.$refs['globalRuleForm'].validate()
|
||||||
let valid = await this.$refs['globalRuleForm'].validate()
|
if (valid) {
|
||||||
if (valid) {
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var visitTaskAnswerList = []
|
var visitTaskAnswerList = []
|
||||||
this.globalForm.taskList.forEach((item, index) => {
|
this.globalForm.taskList.forEach((item, index) => {
|
||||||
|
|
@ -401,24 +400,22 @@ export default {
|
||||||
trialId: this.globalInfo.trialId,
|
trialId: this.globalInfo.trialId,
|
||||||
visitTaskAnswerList
|
visitTaskAnswerList
|
||||||
}
|
}
|
||||||
await batchSubmitGlobalReadingInfo(params)
|
try {
|
||||||
this.loading = false
|
await batchSubmitGlobalReadingInfo(params)
|
||||||
if (isPrompt) {
|
this.loading = false
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
if (isPrompt) {
|
||||||
|
console.log(isPrompt)
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
this.$emit('getGlInfo')
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
this.$emit('getGlInfo')
|
|
||||||
resolve(true)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resolve(false)
|
reject()
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
getBeforeAnswer(qsId, row) {
|
getBeforeAnswer(qsId, row) {
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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,9 +364,8 @@ export default {
|
||||||
},
|
},
|
||||||
handleSave(isPrompt = true) {
|
handleSave(isPrompt = true) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
let valid = await this.$refs['globalRuleForm'].validate()
|
||||||
let valid = await this.$refs['globalRuleForm'].validate()
|
if (valid) {
|
||||||
if (valid) {
|
|
||||||
this.loading = true
|
this.loading = true
|
||||||
var visitTaskAnswerList = []
|
var visitTaskAnswerList = []
|
||||||
this.globalForm.taskList.forEach((item, index) => {
|
this.globalForm.taskList.forEach((item, index) => {
|
||||||
|
|
@ -395,23 +394,22 @@ export default {
|
||||||
trialId: this.globalInfo.trialId,
|
trialId: this.globalInfo.trialId,
|
||||||
visitTaskAnswerList
|
visitTaskAnswerList
|
||||||
}
|
}
|
||||||
await batchSubmitGlobalReadingInfo(params)
|
try {
|
||||||
this.loading = false
|
await batchSubmitGlobalReadingInfo(params)
|
||||||
if (isPrompt) {
|
this.loading = false
|
||||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
if (isPrompt) {
|
||||||
|
console.log(isPrompt)
|
||||||
|
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||||
|
}
|
||||||
|
this.$emit('getGlInfo')
|
||||||
|
resolve()
|
||||||
|
} catch (e) {
|
||||||
|
this.loading = false
|
||||||
|
reject()
|
||||||
}
|
}
|
||||||
this.$emit('getGlInfo')
|
|
||||||
resolve(true)
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
resolve(false)
|
reject()
|
||||||
}
|
}
|
||||||
} catch(e) {
|
|
||||||
console.log(e)
|
|
||||||
this.loading = false
|
|
||||||
resolve(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@
|
||||||
{{ $t('trials:globalReview:button:submit') }}
|
{{ $t('trials:globalReview:button:submit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<customize-table
|
<CustomizeTable
|
||||||
v-if="CriterionType === 0 && Object.keys(globalInfo).length !== 0"
|
v-if="CriterionType === 0 && Object.keys(globalInfo).length !== 0"
|
||||||
ref="globalTbl"
|
ref="globalTbl"
|
||||||
:global-info="globalInfo"
|
:global-info="globalInfo"
|
||||||
|
|
@ -50,7 +50,7 @@
|
||||||
@getGlInfo="getGlInfo"
|
@getGlInfo="getGlInfo"
|
||||||
@setOpenWindow="setOpenWindow"
|
@setOpenWindow="setOpenWindow"
|
||||||
/>
|
/>
|
||||||
<recist-table
|
<RecistTable
|
||||||
v-if="CriterionType === 1 && Object.keys(globalInfo).length !== 0"
|
v-if="CriterionType === 1 && Object.keys(globalInfo).length !== 0"
|
||||||
ref="globalTbl"
|
ref="globalTbl"
|
||||||
:global-info="globalInfo"
|
:global-info="globalInfo"
|
||||||
|
|
@ -59,7 +59,7 @@
|
||||||
@getGlInfo="getGlInfo"
|
@getGlInfo="getGlInfo"
|
||||||
@setOpenWindow="setOpenWindow"
|
@setOpenWindow="setOpenWindow"
|
||||||
/>
|
/>
|
||||||
<lugano-table
|
<LuganoTable
|
||||||
v-if="CriterionType === 2 && Object.keys(globalInfo).length !== 0"
|
v-if="CriterionType === 2 && Object.keys(globalInfo).length !== 0"
|
||||||
ref="globalTbl"
|
ref="globalTbl"
|
||||||
:global-info="globalInfo"
|
:global-info="globalInfo"
|
||||||
|
|
@ -69,7 +69,7 @@
|
||||||
@handleView="handleView"
|
@handleView="handleView"
|
||||||
@setOpenWindow="setOpenWindow"
|
@setOpenWindow="setOpenWindow"
|
||||||
/>
|
/>
|
||||||
<pcwg3-table
|
<PCWG3Table
|
||||||
v-if="CriterionType === 10 && Object.keys(globalInfo).length !== 0"
|
v-if="CriterionType === 10 && Object.keys(globalInfo).length !== 0"
|
||||||
ref="globalTbl"
|
ref="globalTbl"
|
||||||
:global-info="globalInfo"
|
:global-info="globalInfo"
|
||||||
|
|
@ -79,7 +79,7 @@
|
||||||
@handleView="handleView"
|
@handleView="handleView"
|
||||||
@setOpenWindow="setOpenWindow"
|
@setOpenWindow="setOpenWindow"
|
||||||
/>
|
/>
|
||||||
<irecist-table
|
<IRecistTable
|
||||||
v-if="CriterionType === 3 && Object.keys(globalInfo).length !== 0"
|
v-if="CriterionType === 3 && Object.keys(globalInfo).length !== 0"
|
||||||
ref="globalTbl"
|
ref="globalTbl"
|
||||||
:global-info="globalInfo"
|
:global-info="globalInfo"
|
||||||
|
|
@ -88,7 +88,7 @@
|
||||||
@getGlInfo="getGlInfo"
|
@getGlInfo="getGlInfo"
|
||||||
@setOpenWindow="setOpenWindow"
|
@setOpenWindow="setOpenWindow"
|
||||||
/>
|
/>
|
||||||
<recistbm-table
|
<RecistBMTable
|
||||||
v-if="CriterionType === 17 && Object.keys(globalInfo).length !== 0"
|
v-if="CriterionType === 17 && Object.keys(globalInfo).length !== 0"
|
||||||
ref="globalTbl"
|
ref="globalTbl"
|
||||||
:global-info="globalInfo"
|
:global-info="globalInfo"
|
||||||
|
|
@ -97,15 +97,6 @@
|
||||||
@getGlInfo="getGlInfo"
|
@getGlInfo="getGlInfo"
|
||||||
@setOpenWindow="setOpenWindow"
|
@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>
|
||||||
|
|
||||||
|
|
@ -173,17 +164,16 @@ import const_ from '@/const/sign-code'
|
||||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
import CustomizeTable from './components/CustomizeTable'
|
import CustomizeTable from './components/CustomizeTable'
|
||||||
import RecistTable from './components/RecistTable'
|
import RecistTable from './components/RecistTable'
|
||||||
import pcwg3Table from './components/PCWG3Table'
|
import PCWG3Table from './components/PCWG3Table'
|
||||||
import irecistTable from './components/IRecistTable'
|
import IRecistTable from './components/IRecistTable'
|
||||||
import recistbmTable from './components/RecistBMTable'
|
import RecistBMTable from './components/RecistBMTable'
|
||||||
import luganoTable from './components/LuganoTable'
|
import LuganoTable from './components/LuganoTable'
|
||||||
import mrecistTable from './components/MRecistTable.vue'
|
|
||||||
import SignForm from '@/views/trials/components/newSignForm'
|
import SignForm from '@/views/trials/components/newSignForm'
|
||||||
import { changeURLStatic } from '@/utils/history.js'
|
import { changeURLStatic } from '@/utils/history.js'
|
||||||
import store from '@/store'
|
import store from '@/store'
|
||||||
export default {
|
export default {
|
||||||
name: 'GlobalReview',
|
name: 'GlobalReview',
|
||||||
components: { CustomizeTable, RecistTable, pcwg3Table, irecistTable, recistbmTable,luganoTable,mrecistTable, SignForm },
|
components: { CustomizeTable, RecistTable, PCWG3Table, IRecistTable, RecistBMTable,LuganoTable, SignForm },
|
||||||
props: {
|
props: {
|
||||||
trialId: {
|
trialId: {
|
||||||
type: String,
|
type: String,
|
||||||
|
|
@ -394,13 +384,10 @@ export default {
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
} else {
|
} else {
|
||||||
// 自动保存
|
// 自动保存
|
||||||
let res = await this.$refs['globalTbl'].handleSave(false)
|
await this.$refs['globalTbl'].handleSave(false)
|
||||||
if (res) {
|
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
this.signCode = ImageAssessmentReportConfirmation
|
||||||
this.signCode = ImageAssessmentReportConfirmation
|
this.signVisible = true
|
||||||
this.signVisible = true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 关闭签名框
|
// 关闭签名框
|
||||||
|
|
@ -471,7 +458,7 @@ export default {
|
||||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
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 trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
||||||
|
|
||||||
var path = "";
|
var path = "";
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${
|
||||||
this.rowData.SubjectCode
|
this.rowData.SubjectCode
|
||||||
}&subjectId=${
|
}&subjectId=${
|
||||||
|
|
@ -355,7 +355,7 @@ export default {
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
||||||
|
|
||||||
var path = "";
|
var path = "";
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${
|
||||||
this.rowData.SubjectCode
|
this.rowData.SubjectCode
|
||||||
}&subjectId=${this.rowData.SubjectId}&visitTaskId=${
|
}&subjectId=${this.rowData.SubjectId}&visitTaskId=${
|
||||||
|
|
|
||||||
|
|
@ -320,7 +320,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.rowData.IsReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.rowData.IsReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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()}`
|
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 {
|
} 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()}`
|
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()}`
|
||||||
|
|
|
||||||
|
|
@ -201,7 +201,7 @@ export default {
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
|
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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()}`
|
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 {
|
} 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()}`
|
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 trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
|
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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()}`
|
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 {
|
} 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()}`
|
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 trialReadingCriterionId = row.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
|
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
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()}`
|
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 {
|
} 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()}`
|
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 isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
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) {
|
lookReadingResults(row) {
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path
|
var path
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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)
|
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path = ''
|
var path = ''
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2 ) {
|
if (row.ReadingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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 isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var criterionType = this.$router.currentRoute.query.criterionType
|
var criterionType = this.$router.currentRoute.query.criterionType
|
||||||
var path = ''
|
var path = ''
|
||||||
if (this.readingTool === 0 || this.readingTool === 2 ) {
|
if (this.readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
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 token = getToken()
|
||||||
var path = ''
|
var path = ''
|
||||||
if (this.readingTool === 0 || this.readingTool === 2) {
|
if (this.readingTool === 0) {
|
||||||
if (this.criterionType === 0 && this.trialId === '08dd28b3-6843-fc05-0242-ac1301000000') {
|
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}`
|
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 {
|
} else {
|
||||||
|
|
@ -468,7 +468,7 @@ export default {
|
||||||
)
|
)
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path = ''
|
var path = ''
|
||||||
if (this.readingTool === 0 || this.readingTool === 2 ) {
|
if (this.readingTool === 0) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
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 token = getToken()
|
||||||
var path
|
var path
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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,29 +601,10 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<!-- 退回影响任务列表/已影响任务列表 -->
|
<!-- 退回影响任务列表/已影响任务列表 -->
|
||||||
<el-dialog v-if="ReReadingOrBackVisible" :title="opentype === 'read'
|
<el-dialog v-if="ReReadingOrBackVisible" :title="opentype === 'read'
|
||||||
? $t('trials:reviewTrack:action:back')
|
? $t('trials:reviewTrack:dialog:backImpactList')
|
||||||
: $t('trials:reviewTrack:dialog:impactList')
|
: $t('trials:reviewTrack:dialog:impactList')
|
||||||
" :visible.sync="ReReadingOrBackVisible" width="1460px" append-to-body :close-on-click-modal="false"
|
" :visible.sync="ReReadingOrBackVisible" width="1460px" append-to-body :close-on-click-modal="false"
|
||||||
custom-class="base-dialog-wrapper">
|
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">
|
<div class="base-dialog-body">
|
||||||
<el-table v-loading="loading" :data="InfluenceTaskList" stripe height="100" style="min-height: 400px">
|
<el-table v-loading="loading" :data="InfluenceTaskList" stripe height="100" style="min-height: 400px">
|
||||||
<!-- 任务编号 -->
|
<!-- 任务编号 -->
|
||||||
|
|
@ -752,8 +733,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div slot="footer" class="dialog-footer" v-if="opentype === 'read'">
|
<div slot="footer" class="dialog-footer" v-if="opentype === 'read'">
|
||||||
<!-- 取消 -->
|
<!-- 取消 -->
|
||||||
<el-button :disabled="btnLoading" size="small" type="primary"
|
<el-button :disabled="btnLoading" size="small" type="primary" @click="ReReadingOrBackVisible = false">
|
||||||
@click="ReReadingOrBackVisible = false, backforReasonForm = { pmBackReason: null }">
|
|
||||||
{{ $t('common:button:cancel') }}
|
{{ $t('common:button:cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 确定 -->
|
<!-- 确定 -->
|
||||||
|
|
@ -948,9 +928,6 @@ export default {
|
||||||
Type: null,
|
Type: null,
|
||||||
RequestReReadingReason: null,
|
RequestReReadingReason: null,
|
||||||
},
|
},
|
||||||
backforReasonForm: {
|
|
||||||
pmBackReason: null
|
|
||||||
},
|
|
||||||
rules: {
|
rules: {
|
||||||
Type: [
|
Type: [
|
||||||
{
|
{
|
||||||
|
|
@ -966,13 +943,6 @@ export default {
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
pmBackReason: [
|
|
||||||
{
|
|
||||||
required: true,
|
|
||||||
message: this.$t('common:ruleMessage:specify'),
|
|
||||||
trigger: 'blur',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
RefereeAllocationVisible: false,
|
RefereeAllocationVisible: false,
|
||||||
trialId: this.$route.query.trialId,
|
trialId: this.$route.query.trialId,
|
||||||
|
|
@ -1105,16 +1075,10 @@ export default {
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
async PMSetTaskBack() {
|
PMSetTaskBack() {
|
||||||
try {
|
this.loading = true
|
||||||
let validate = await this.$refs.backReasonForm.validate()
|
PMSetTaskBack(this.trialId, this.rowData.Id)
|
||||||
console.log(validate, 'validate')
|
.then((res) => {
|
||||||
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.loading = false
|
||||||
this.ReReadingOrBackVisible = false
|
this.ReReadingOrBackVisible = false
|
||||||
this.getList()
|
this.getList()
|
||||||
|
|
@ -1122,25 +1086,10 @@ export default {
|
||||||
this.$message.success(
|
this.$message.success(
|
||||||
this.$t('trials:reviewTrack:message:returnedSuccessfully')
|
this.$t('trials:reviewTrack:message:returnedSuccessfully')
|
||||||
)
|
)
|
||||||
}
|
})
|
||||||
} catch (err) {
|
.catch(() => {
|
||||||
this.loading = false
|
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) {
|
openReReadingOrBackList(row) {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
@ -1150,9 +1099,6 @@ export default {
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
this.InfluenceTaskList = res.Result
|
this.InfluenceTaskList = res.Result
|
||||||
this.ReReadingOtherInfo = res.OtherInfo
|
this.ReReadingOtherInfo = res.OtherInfo
|
||||||
this.backforReasonForm = {
|
|
||||||
pmBackReason: null
|
|
||||||
}
|
|
||||||
this.ReReadingOrBackVisible = true
|
this.ReReadingOrBackVisible = true
|
||||||
this.loading = false
|
this.loading = false
|
||||||
})
|
})
|
||||||
|
|
@ -1167,7 +1113,7 @@ export default {
|
||||||
}
|
}
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path
|
var path
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0) {
|
||||||
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}`
|
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 {
|
} 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}`
|
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}`
|
||||||
|
|
|
||||||
|
|
@ -390,7 +390,7 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||||
this.readingTaskState = this.taskInfo.ReadingTaskState
|
this.readingTaskState = this.taskInfo.ReadingTaskState
|
||||||
if (!this.taskInfo.IsBaseLine && this.taskInfo.IsReadingTaskViewInOrder !== 0) {
|
if (this.taskInfo.VisitNum > 0 && this.taskInfo.IsReadingTaskViewInOrder !== 0) {
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
this.cols = 2
|
this.cols = 2
|
||||||
this.activeCanvasIndex = 1
|
this.activeCanvasIndex = 1
|
||||||
|
|
|
||||||
|
|
@ -200,8 +200,7 @@ export default {
|
||||||
this.$refs[res.Result[idx].VisitTaskId][0].setInitActiveFile()
|
this.$refs[res.Result[idx].VisitTaskId][0].setInitActiveFile()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (this.taskInfo.IsReadingTaskViewInOrder === 1 && res.Result.length > 1) {
|
if (this.taskInfo.IsReadingTaskViewInOrder !== 0 && res.Result.length > 1) {
|
||||||
// 按时间顺序
|
|
||||||
const i = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
|
const i = this.visitTaskList.findIndex(i => i.IsBaseLineTask)
|
||||||
if (i > -1) {
|
if (i > -1) {
|
||||||
await this.getReadingImageFile(res.Result[i].VisitTaskId, i)
|
await this.getReadingImageFile(res.Result[i].VisitTaskId, i)
|
||||||
|
|
@ -216,14 +215,6 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.taskInfo.IsReadingTaskViewInOrder === 2) {
|
|
||||||
// 受试者内随机
|
|
||||||
const studyList = this.visitTaskList[idx].StudyList
|
|
||||||
if (studyList.length > 0) {
|
|
||||||
const fileInfo = studyList[0].NoneDicomStudyFileList[0]
|
|
||||||
this.relatedStudyInfo = { fileInfo, visitTaskInfo: this.visitTaskList[idx], fileList: studyList[0].NoneDicomStudyFileList, fileIndex: 0, studyId: studyList[0].Id }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
|
|
@ -295,8 +286,8 @@ export default {
|
||||||
async toggleTaskByViewer(visitTaskNum) {
|
async toggleTaskByViewer(visitTaskNum) {
|
||||||
const i = this.visitTaskList.findIndex(v => v.VisitTaskNum === visitTaskNum)
|
const i = this.visitTaskList.findIndex(v => v.VisitTaskNum === visitTaskNum)
|
||||||
if (i === -1) return
|
if (i === -1) return
|
||||||
const visitTaskId = this.visitTaskList[i].VisitTaskId
|
const visistTaskId = this.visitTaskList[i].VisitTaskId
|
||||||
this.setActiveTaskVisitId(visitTaskId, true)
|
this.setActiveTaskVisitId(visistTaskId, true)
|
||||||
},
|
},
|
||||||
// 设置激活的访视
|
// 设置激活的访视
|
||||||
async setActiveTaskVisitId(id, isInitActiveFile = false) {
|
async setActiveTaskVisitId(id, isInitActiveFile = false) {
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,7 @@
|
||||||
<!-- 级别: -->
|
<!-- 级别: -->
|
||||||
<el-form-item :label="$t('trials:qcCfg:table:level')">
|
<el-form-item :label="$t('trials:qcCfg:table:level')">
|
||||||
<el-select v-model="searchData.IsDefeaultViewParent" style="width:120px;">
|
<el-select v-model="searchData.IsDefeaultViewParent" style="width:120px;">
|
||||||
<el-option v-for="item of $d.IsDefeaultViewParentLevel" :key="item.id" :value="item.value"
|
<el-option v-for="item of $d.IsDefeaultViewParentLevel" :key="item.id" :value="item.value" :label="item.label" />
|
||||||
:label="item.label" />
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item>
|
<el-form-item>
|
||||||
|
|
@ -26,50 +25,87 @@
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
<span style="margin-left:auto">
|
<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') }}
|
{{ $t('common:button:submit') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table ref="qsList" :data="list" stripe size="small" height="400" @selection-change="handleSelectChange"
|
<el-table
|
||||||
@select="handleselect" @select-all="handleselectAll">
|
ref="qsList"
|
||||||
|
:data="list"
|
||||||
|
stripe
|
||||||
|
size="small"
|
||||||
|
height="400"
|
||||||
|
@selection-change="handleSelectChange"
|
||||||
|
@select="handleselect"
|
||||||
|
>
|
||||||
<el-table-column type="selection" align="left" width="45" :selectable="handleSelectTable" />
|
<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">
|
<template slot-scope="scope">
|
||||||
{{ $fd('QcType', scope.row.Type) }}
|
{{ $fd('QcType', scope.row.Type) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 选项 -->
|
<!-- 选项 -->
|
||||||
<el-table-column prop="TypeValue" :label="$t('trials:qcCfg:table:typeValue')" show-overflow-tooltip
|
<el-table-column
|
||||||
min-width="110" />
|
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
|
<el-table-column
|
||||||
width="120" />
|
prop="ParentShowOrder"
|
||||||
|
:label="$t('trials:qcCfg:table:parentQs')"
|
||||||
|
show-overflow-tooltip
|
||||||
|
width="120"
|
||||||
|
/>
|
||||||
<!-- 父问题触发值 -->
|
<!-- 父问题触发值 -->
|
||||||
<el-table-column prop="ParentTriggerValue" :label="$t('trials:qcCfg:table:parentTriggerValue')"
|
<el-table-column
|
||||||
show-overflow-tooltip />
|
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">
|
<template slot-scope="scope">
|
||||||
{{ $fd('YesOrNo', scope.row.IsRequired) }}
|
{{ $fd('YesOrNo', scope.row.IsRequired) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</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">
|
<template slot-scope="scope">
|
||||||
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<Pagination style="margin-top: 10px" class="page" :total="total" :page.sync="searchData.PageIndex"
|
<Pagination style="margin-top: 10px" class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
|
||||||
:limit.sync="searchData.PageSize" @pagination="getList" />
|
|
||||||
</box-content>
|
</box-content>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -108,7 +144,7 @@ export default {
|
||||||
computed: {
|
computed: {
|
||||||
...mapGetters(['language'])
|
...mapGetters(['language'])
|
||||||
},
|
},
|
||||||
created() {
|
created(){
|
||||||
this.trialId = this.$route.query.trialId;
|
this.trialId = this.$route.query.trialId;
|
||||||
this.getList();
|
this.getList();
|
||||||
},
|
},
|
||||||
|
|
@ -129,13 +165,7 @@ export default {
|
||||||
}).catch(() => { this.loading = false })
|
}).catch(() => { this.loading = false })
|
||||||
},
|
},
|
||||||
handleSelectChange(val) {
|
handleSelectChange(val) {
|
||||||
// this.selectArr = val
|
this.selectArr = val
|
||||||
},
|
|
||||||
handleselectAll(selection) {
|
|
||||||
this.selectArr = []
|
|
||||||
if (selection.length > 0) {
|
|
||||||
this.selectArr = this.list
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
handleselect(selection, row) {
|
handleselect(selection, row) {
|
||||||
const selected = selection.length && selection.indexOf(row) !== -1
|
const selected = selection.length && selection.indexOf(row) !== -1
|
||||||
|
|
@ -145,22 +175,6 @@ export default {
|
||||||
arr.map(item => {
|
arr.map(item => {
|
||||||
this.$refs.qsList.toggleRowSelection(item, selected)
|
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() {
|
handleSubmit() {
|
||||||
this.loading = true
|
this.loading = true
|
||||||
|
|
|
||||||
|
|
@ -64,28 +64,6 @@
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</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
|
<el-form-item
|
||||||
:label="$t('trials:processCfg:form:IsImageFilter')"
|
:label="$t('trials:processCfg:form:IsImageFilter')"
|
||||||
|
|
@ -615,7 +593,6 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { getCriterionReadingInfo, setCriterionReadingInfo } from '@/api/trials'
|
import { getCriterionReadingInfo, setCriterionReadingInfo } from '@/api/trials'
|
||||||
import { config } from '@/views/trials/trials-panel/reading/dicoms3D/components/toolConfig'
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ReadingRules',
|
name: 'ReadingRules',
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -637,8 +614,6 @@ export default {
|
||||||
TrialId: '',
|
TrialId: '',
|
||||||
ImagePlatform: null,
|
ImagePlatform: null,
|
||||||
ReadingTool: 0,
|
ReadingTool: 0,
|
||||||
ReadingVersionEnum: null,
|
|
||||||
ReadingToolList: [],
|
|
||||||
ReadingTaskViewEnum: null,
|
ReadingTaskViewEnum: null,
|
||||||
IsImageLabeled: null,
|
IsImageLabeled: null,
|
||||||
IsReadingShowSubjectInfo: null,
|
IsReadingShowSubjectInfo: null,
|
||||||
|
|
@ -832,14 +807,9 @@ export default {
|
||||||
modalityList: [],
|
modalityList: [],
|
||||||
CriterionModalitys: [],
|
CriterionModalitys: [],
|
||||||
modalityIsCheck: false, // 是否允许影像筛选
|
modalityIsCheck: false, // 是否允许影像筛选
|
||||||
tools: []
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
if (this.CriterionType === 0) {
|
|
||||||
this.tools = [...config.customizeStandards]
|
|
||||||
}
|
|
||||||
|
|
||||||
this.initPage()
|
this.initPage()
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
|
||||||