Compare commits
221 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 47594536f1 | |||
| 17b1cc476f | |||
| 6cd5e7b957 | |||
| 8122464fbb | |||
| 56bc2bc5cd | |||
| 691a3721a0 | |||
| 4efcaa915c | |||
| 903faf405e | |||
| 9da598862a | |||
| 365791624e | |||
| d7a8112441 | |||
| d05ea6c28d | |||
| 74547d7bff | |||
| 41eb974496 | |||
| 6ee3a06eb2 | |||
| b4821ace59 | |||
| 612270eaad | |||
| 5cce828ad9 | |||
| 38d8ac5ae5 | |||
| b8dfcfea1d | |||
| 47f885b551 | |||
| 010a5867b5 | |||
| 6f2bc9f7f5 | |||
| c31bc89746 | |||
| a037209770 | |||
| c675e21c40 | |||
| 8aa067e52f | |||
| 20c257be4f | |||
| 64cec20d7d | |||
| 88a7634ed3 | |||
| cbb73d68e1 | |||
| feb205d05e | |||
| ccc6ee90cb | |||
| 75059297ad | |||
| 0df193c474 | |||
| 7d9be5e2b3 | |||
| df417afbbb | |||
| 48c76cb0bb | |||
| 83182a4d0f | |||
| 10408bde30 | |||
| 1705469056 | |||
| 8f5b75fcd5 | |||
| 0c3a69d4d0 | |||
| 2683a5a7c9 | |||
| d17b95a200 | |||
| 9a8bf1e637 | |||
| 4aa43b009b | |||
| bb798ce4ad | |||
| da4cc0a8ef | |||
| fb55a1d536 | |||
| 2986d43f39 | |||
| 13c9c9b4c3 | |||
| d0a7a4132f | |||
| dffad5a122 | |||
| ef3ca59842 | |||
| 1aaf1927f5 | |||
| 6fab860497 | |||
| f3ff162cdd | |||
| b7655ebad0 | |||
| 79df77b30c | |||
| cfe03844a7 | |||
| 6eebf590f8 | |||
| c09220dbd3 | |||
| 2dd2aeede7 | |||
| 5ae8348765 | |||
| 3b8505ba3a | |||
| fe8398df9d | |||
| 27caa4ff77 | |||
| 3b96a5326e | |||
| 9b63c2c82e | |||
| 342f833eb8 | |||
| 56b00791f4 | |||
| 474c0dca70 | |||
| a7806d07bb | |||
| f6e87596ee | |||
| d1448d4cc6 | |||
| bf985bcbc8 | |||
| 70db0d9258 | |||
| 8f1ab432b2 | |||
| 3f0573eeb3 | |||
| 2ed051e25b | |||
| dde53103f9 | |||
| 042a5fe59b | |||
| 8dda50f78e | |||
| 7c06c94177 | |||
| 42652cd9ee | |||
| 2370c25ed7 | |||
| cdefe6d640 | |||
| 9ef348efbf | |||
| 06e876619f | |||
| 3334e24c66 | |||
| 9b3e169ef2 | |||
| fa30c68153 | |||
| e08f094435 | |||
| d047df807e | |||
| 2c5e33903d | |||
| b024252f98 | |||
| c1be3bbf4d | |||
| f2b07131aa | |||
| 6c71803a11 | |||
| 91078abd15 | |||
| 04f8a938c3 | |||
| 2c85013008 | |||
| 9d839e46cd | |||
| 509f8f02b6 | |||
| 9cc1962b3b | |||
| 774ab78a7c | |||
| 16794dfe1d | |||
| 1c69ed08cd | |||
| 833324e1ac | |||
| f36a00cf81 | |||
| 233bcbb1d0 | |||
| b644098203 | |||
| 424a59c4d9 | |||
| a3e3db3d5b | |||
| a803ee2c00 | |||
| 5a8ec13c2f | |||
| d911d55129 | |||
| ebedae85e7 | |||
| d54dfae99f | |||
| 00396f3c9d | |||
| 2138bd3345 | |||
| 0416b1bca8 | |||
| 6dd579e910 | |||
| 98dc6beba5 | |||
| f7a62b2016 | |||
| eb50f24204 | |||
| 3c4cce70c5 | |||
| a566c1a0b8 | |||
| 3bdd567f1e | |||
| cbbbb227ea | |||
| 91dc08493b | |||
| bacdbd9fa1 | |||
| 3d096f397f | |||
| 4f7a308cf1 | |||
| bb3e3e52a5 | |||
| f918004dda | |||
| fd683d74f9 | |||
| d7838051e8 | |||
| b727d6b068 | |||
| 3b14944671 | |||
| 2b820a114b | |||
| 3f69434251 | |||
| ee545589af | |||
| feed991971 | |||
| a56b536e95 | |||
| eaf856a755 | |||
| 8f497ed363 | |||
| c33c2d6a09 | |||
| cc788b9833 | |||
| 0aaf2f3edb | |||
| 2a80893932 | |||
| 6a0859aaab | |||
| 690b29c5c5 | |||
| 0d3cb15806 | |||
| 4b32c290e7 | |||
| 390df569c9 | |||
| 05c6e9727f | |||
| 87eac9f478 | |||
| ef489552ea | |||
| dd80abed02 | |||
| 6ce18843ee | |||
| fb48b59587 | |||
| ed2b75d331 | |||
| 0c040719b0 | |||
| 5dc5213202 | |||
| bdfef06b5f | |||
| 1d009c8e18 | |||
| c03e85ff22 | |||
| 0a752ed92f | |||
| eab207fc35 | |||
| 5ef755249c | |||
| 8da7b81235 | |||
| 276d8adac0 | |||
| 12da4c5d9f | |||
| 850d64f0aa | |||
| 541d44b4f2 | |||
| a1137c0a5b | |||
| e2e20a24fd | |||
| 2f1fcfa81d | |||
| ba4a5c0d1d | |||
| face77f949 | |||
| de80b75c0b | |||
| f050df725e | |||
| 290210c27e | |||
| be2651501d | |||
| 2df6c37fd0 | |||
| 34cc69abb0 | |||
| 26914c2b2b | |||
| 98ce2b27da | |||
| 5805ea0778 | |||
| 17737d901c | |||
| 51a94ad89e | |||
| a2491c4ba5 | |||
| 9187c9db8c | |||
| 5e67f8b65f | |||
| 6218b536f9 | |||
| 7493c1a98a | |||
| d91a9170de | |||
| 3d0a3116e1 | |||
| 76e41f4d5f | |||
| 57bec076b7 | |||
| 36ea567229 | |||
| d3a4842504 | |||
| e9dd669d48 | |||
| 4d27cbfe41 | |||
| 13cfcb0935 | |||
| 8c40241658 | |||
| b8208dffed | |||
| 10b8cc6a5e | |||
| edf1377374 | |||
| f8b4dd70c8 | |||
| 71acbc5f78 | |||
| 33a8d8743e | |||
| a357fe7ce6 | |||
| 07fbbf5a74 | |||
| 79b14eee67 | |||
| 9f76310101 | |||
| 1bacf16361 | |||
| 4b700b5db3 | |||
| b7f4cccbfa |
@@ -11,6 +11,14 @@
|
||||
<meta http-equiv="Cache-control" content="no-store,no-cache,must-revalidate">
|
||||
<meta http-equiv="Cache" content="no-cache">
|
||||
<title><%= webpackConfig.name %></title>
|
||||
<style>
|
||||
.customPromptTip {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: -100px;
|
||||
z-index: 99999;
|
||||
}
|
||||
</style>
|
||||
<% if (eval(process.env.VUE_APP_LOGIN_FOR_PERMISSION)) { %>
|
||||
<script>
|
||||
window.zzSessionStorage = {
|
||||
|
||||
@@ -281,7 +281,13 @@ export function getCommonDocumentList(param) {
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
export function getCommonDocument(param) {
|
||||
return request({
|
||||
url: `/CommonDocument/getCommonDocument`,
|
||||
method: 'get',
|
||||
params: param
|
||||
})
|
||||
}
|
||||
export function addOrUpdateCommonDocument(param) {
|
||||
return request({
|
||||
url: `/CommonDocument/addOrUpdateCommonDocument`,
|
||||
|
||||
@@ -203,6 +203,15 @@ export function qCVisitList_Export(data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出影像指控问题和答案
|
||||
export function GetTrialQCQuestionAnserList_Export(data) {
|
||||
return requestDownload({
|
||||
url: `/ExcelExport/GetTrialQCQuestionAnserList_Export`,
|
||||
responseType: 'blob',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出下载记录
|
||||
export function getTrialDownloadList_Export(data) {
|
||||
return requestDownload({
|
||||
@@ -230,6 +239,14 @@ export function getPatientList_Export(data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
export function getTumor_CDISC_Export(data) {
|
||||
return requestDownload({
|
||||
url: `/IVUS_OCTExport/getTumor_CDISC_Export`,
|
||||
responseType: 'blob',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
export function getCommonEvaluationList_Export(data) {
|
||||
return requestDownload({
|
||||
url: `/ExcelExport/getCommonEvaluationList_Export`,
|
||||
@@ -273,3 +290,21 @@ export function GetEmailNoticeConfigList_Export(data) {
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出重传审批
|
||||
export function GetImageBackList_Export(data) {
|
||||
return requestDownload({
|
||||
url: `/ExcelExport/GetImageBackList_Export`,
|
||||
responseType: 'blob',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 导出医学审核配置
|
||||
export function GetReadingMedicineSystemQuestionList_Export(data) {
|
||||
return requestDownload({
|
||||
url: `/ExcelExport/GetReadingMedicineSystemQuestionList_Export`,
|
||||
responseType: 'blob',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
+23
-5
@@ -45,10 +45,11 @@ export function saveImageLabelList(param) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getStudyInfo(studyId) {
|
||||
export function getStudyInfo(studyId, params) {
|
||||
return request({
|
||||
url: `/Study/item/${studyId}`,
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
export function getSeriesList(url) {
|
||||
@@ -75,10 +76,11 @@ export function getRelationVisitList(visitNum, tpCode) {
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
export function getAllRelationStudyList(studyId) {
|
||||
export function getAllRelationStudyList(studyId, params) {
|
||||
return request({
|
||||
url: `/study/getAllRelationStudyList/${studyId}`,
|
||||
method: 'get'
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
export function getTrialListByReviewer(param) {
|
||||
@@ -134,7 +136,7 @@ export function AddAdjudicationReport(param) {
|
||||
}
|
||||
|
||||
export function getVisitStudyList(trialId, subjectVisitId, isReading, visitTaskId) {
|
||||
let url = `/SubjectVisit/getVisitStudyList/${trialId}/${subjectVisitId}/${isReading}`
|
||||
let url = `/SubjectVisit/getVisitStudyList/${trialId}/${subjectVisitId}/${isReading}`
|
||||
url = visitTaskId ? `${url}?visitTaskId=${visitTaskId}` : url
|
||||
return request({
|
||||
url: url,
|
||||
@@ -284,4 +286,20 @@ export function deleteSingleTableQuestionMark(param, type) {
|
||||
})
|
||||
}
|
||||
|
||||
// 阅片导入
|
||||
export function readingImport(param) {
|
||||
return request({
|
||||
url: `/ReadingCalculate/readingImport`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
// 阅片获取图表数据
|
||||
export function getReportsChartData(param) {
|
||||
return request({
|
||||
url: `/ReadingImageTask/getReportsChartData`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
+99
-6
@@ -969,13 +969,20 @@ export function takeOrReleaseQCTask(trialId, subjectVisitId, obtainOrCancel) {
|
||||
method: 'put'
|
||||
})
|
||||
}
|
||||
export function replaceQCTaskActionUser(trialId, subjectVisitId) {
|
||||
export function replaceQCTaskActionUser(trialId, subjectVisitId, params = {}) {
|
||||
return request({
|
||||
url: `/QCOperation/replaceQCTaskActionUser/${trialId}/${subjectVisitId}`,
|
||||
method: 'put'
|
||||
method: 'put',
|
||||
params
|
||||
})
|
||||
}
|
||||
export function getTrialUserRoleList(params) {
|
||||
return request({
|
||||
url: `/TrialMaintenance/getTrialUserRoleList`,
|
||||
method: 'get',
|
||||
params
|
||||
})
|
||||
}
|
||||
|
||||
export function verifyReuploadIsCanJump(trialId, qcChallengeId) {
|
||||
return request({
|
||||
url: `/QCOperation/verifyReuploadIsCanJump/${trialId}/${qcChallengeId}`,
|
||||
@@ -1398,9 +1405,9 @@ export function getForwardList(param) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false, visitTaskId = '', IsReading = false) {
|
||||
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false, visitTaskId = '', IsReading = false, isImageSegmentLabel = '') {
|
||||
return request({
|
||||
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}&visitTaskId=${visitTaskId}&IsReading=${IsReading}`,
|
||||
url: `/NoneDicomStudy/getNoneDicomStudyList?isImageSegmentLabel=${isImageSegmentLabel}&subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}&visitTaskId=${visitTaskId}&IsReading=${IsReading}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -3037,7 +3044,13 @@ export function readClinicalData(param) {
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
export function viewstudyPart(param) {
|
||||
return request({
|
||||
url: `/ReadingImageTask/viewstudyPart`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function getCustomQuestionPreview(param) {
|
||||
return request({
|
||||
url: `/ReadingQuestion/getCustomQuestionPreview`,
|
||||
@@ -4197,4 +4210,84 @@ export function getExportSubjectVisitImageList(data) {
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 影像质控-更正dicom
|
||||
export function updateDicomStudyInfo(data) {
|
||||
return request({
|
||||
url: `/Inspection/QCOperation/UpdateDicomStudyInfo`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 影像质控-更正非dicom
|
||||
export function updateNoneDicomStudy(data) {
|
||||
return request({
|
||||
url: `/Inspection/NoneDicomStudy/UpdateNoneDicomStudy`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 阅片单元-获取访视计划
|
||||
export function getVisitStage(data) {
|
||||
return request({
|
||||
url: `/VisitPlan/getVisitStage`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 稽查管理-列表
|
||||
export function getAuditRecordList(data) {
|
||||
return request({
|
||||
url: `/AuditDocument/getAuditRecordList`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 稽查管理-列表(EA)
|
||||
export function getAuditRecordSelectList(data) {
|
||||
return request({
|
||||
url: `/AuditDocument/getAuditRecordSelectList`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 稽查管理-列表新增修改
|
||||
export function addOrUpdateAuditRecord(data) {
|
||||
return request({
|
||||
url: `/AuditDocument/addOrUpdateAuditRecord`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 稽查管理-文档授权
|
||||
export function setAuditRecordPermission(data) {
|
||||
return request({
|
||||
url: `/AuditDocument/setAuditRecordPermission`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 稽查管理-人员管理
|
||||
export function addOrDeleteAuditRecordUser(data) {
|
||||
return request({
|
||||
url: `/AuditDocument/addOrDeleteAuditRecordUser`,
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 稽查管理-删除
|
||||
export function deleteAuditRecord(auditRecordId) {
|
||||
return request({
|
||||
url: `/AuditDocument/deleteAuditRecord/${auditRecordId}`,
|
||||
method: 'delete'
|
||||
})
|
||||
}
|
||||
|
||||
// 靶段标注列表
|
||||
export function getTrialSubjectVisitMarkList(data) {
|
||||
return request({
|
||||
url: `/DownloadAndUpload/getTrialSubjectVisitMarkList`,
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 6.1 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 54 KiB |
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div id="canvas" ref="canvas" v-loading="loading" element-loading-text="Loading..."
|
||||
<div id="canvas" ref="canvas" v-loading="loading" :element-loading-text="NSTip"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)" style="width:100%;height:100%;position:relative;"
|
||||
class="cornerstone-element" @contextmenu.prevent="onContextmenu" @mouseup="sliderMouseup">
|
||||
<div v-show="dicomInfo.series" class="info-series">
|
||||
@@ -39,6 +39,8 @@
|
||||
</div>
|
||||
|
||||
<div class="info-subject">
|
||||
<div v-if="series.subjectCode">{{ series.subjectCode }}</div>
|
||||
<div v-if="series.visitName">{{ series.visitName }}</div>
|
||||
<div>{{ stack.description }}</div>
|
||||
<!-- <div>{{ dicomInfo.hospital }}</div> -->
|
||||
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
|
||||
@@ -112,6 +114,11 @@ import DicomTags from './DicomTags'
|
||||
export default {
|
||||
name: 'DicomCanvas',
|
||||
components: { DicomTags },
|
||||
computed: {
|
||||
NSTip() {
|
||||
return `${this.$store.state.trials.downloadSize}, NS: ${this.$store.state.trials.downloadTip}`
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
|
||||
@@ -887,11 +887,11 @@ export default {
|
||||
.dicom-wrapper .dropdown-content {
|
||||
display: none;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
left: -20px;
|
||||
top: 40px;
|
||||
color: #d0d0d0;
|
||||
background-color: #323232;
|
||||
min-width: 80px;
|
||||
min-width: 100px;
|
||||
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
|
||||
border: 1px solid #4e4e4e;
|
||||
padding: 5px;
|
||||
|
||||
@@ -4,7 +4,7 @@ import Preview from "./index.vue";
|
||||
const PreviewConstructor = Vue.extend(Preview);
|
||||
|
||||
const preview = options => {
|
||||
const { path, type, title } = options;
|
||||
const { path, type, title, isLocal = false } = options;
|
||||
if (!path) throw `path is requred.but ${path}`
|
||||
const id = `Preview_${new Date().getTime()}`;
|
||||
const instance = new PreviewConstructor();
|
||||
@@ -12,7 +12,7 @@ const preview = options => {
|
||||
instance.vm = instance.$mount();
|
||||
if (instance.vm.visible) return;
|
||||
document.body.appendChild(instance.vm.$el);
|
||||
instance.vm.open(path, type, title);
|
||||
instance.vm.open(path, type, title, isLocal);
|
||||
instance.vm.$on("closed", () => {
|
||||
document.body.removeChild(instance.vm.$el);
|
||||
instance.vm.$destroy();
|
||||
|
||||
@@ -1,15 +1,8 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
v-if="visible"
|
||||
:visible.sync="visible"
|
||||
:title="title"
|
||||
:fullscreen="true"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
@close="handleClose"
|
||||
>
|
||||
<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">
|
||||
<PreviewFile v-if="visible" :file-path="path" :file-type="type" />
|
||||
<PreviewFile v-if="visible" :file-path="path" :file-type="type" :is-local="isLocal" />
|
||||
</div>
|
||||
</el-dialog>
|
||||
</template>
|
||||
@@ -24,13 +17,15 @@ export default {
|
||||
path: null,
|
||||
type: null,
|
||||
title: null,
|
||||
isLocal: false
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
open(path, type, title) {
|
||||
open(path, type, title, isLocal) {
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
this.title = title;
|
||||
this.isLocal = isLocal;
|
||||
this.visible = true;
|
||||
},
|
||||
handleClose() {
|
||||
|
||||
@@ -5,16 +5,17 @@
|
||||
<!-- <embed v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" style="width: 100%; height: 100%"> -->
|
||||
<!-- <iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" width="100%" height="100%" frameborder="0" /> -->
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1"
|
||||
:src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`"
|
||||
:src="`/static/pdfjs/web/viewer.html?file=${isLocal ? window.location.origin : OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`"
|
||||
width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<!-- <pdf-->
|
||||
<!-- v-else-if="fileType.indexOf('pdf') !== -1"-->
|
||||
<!-- :src="`/static/pdfjs/web/viewer.html?file=${filePath}`">-->
|
||||
<!-- </pdf>-->
|
||||
<video :src="`${OSSclientConfig.basePath}${filePath}`" style="width: 100%;height: 99%;" autoplay controls
|
||||
controlsList="nodownload" v-else-if="fileType.indexOf('mp4') !== -1"></video>
|
||||
<video :src="`${isLocal ? window.location.origin : OSSclientConfig.basePath}${filePath}`"
|
||||
style="width: 100%;height: 99%;" autoplay controls controlsList="nodownload"
|
||||
v-else-if="fileType.indexOf('mp4') !== -1"></video>
|
||||
<iframe v-else
|
||||
:src="`/static/onlyOffice/viewer.html?url=${OSSclientConfig.basePath}${filePath}?onlyOffice_url=${onlyOffice_url}&type=${fileType}&title=${title}&documentType=${documentType}&userName=${currentUser}`"
|
||||
:src="`/static/onlyOffice/viewer.html?url=${isLocal ? window.location.origin : 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') }}
|
||||
@@ -43,12 +44,17 @@ export default {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
isLocal: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY: process.env.VUE_APP_COMPANY_NAME,
|
||||
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL
|
||||
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL,
|
||||
window
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
{{ question.QuestionName }}
|
||||
</span>
|
||||
<!-- 添加 -->
|
||||
<el-button type="primary" size="mini" @click="openAddTableCol(question)">
|
||||
<el-button type="primary" size="mini" @click="openAddTableCol(question)" v-if="SecondReviewState <= 0">
|
||||
{{ $t('trials:readingUnit:qsList:title:add') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -29,7 +29,8 @@
|
||||
: scope.row[item.Id] }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common:action:action')" min-width="100" show-overflow-tooltip>
|
||||
<el-table-column :label="$t('common:action:action')" min-width="100" show-overflow-tooltip
|
||||
v-if="SecondReviewState <= 0">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="openAddTableCol(question, scope.$index)">
|
||||
{{ $t('common:button:edit') }}
|
||||
@@ -164,7 +165,6 @@
|
||||
import { getTrialClinicalQuestionCalculateRelation } from '@/api/dictionary'
|
||||
import QuestionTableFormItem from './QuestionTableFormItem'
|
||||
import { mapGetters } from 'vuex'
|
||||
import DicomEvent from "../../../views/trials/trials-panel/reading/dicoms/components/DicomEvent";
|
||||
|
||||
export default {
|
||||
name: 'QuestionFormItem',
|
||||
@@ -176,6 +176,10 @@ export default {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
SecondReviewState: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
|
||||
@@ -4,11 +4,12 @@
|
||||
:disabled="openType === 'look'">
|
||||
<template>
|
||||
<QuestionFormItem class="father" v-for="question of questions" :key="question.Id" :question="question"
|
||||
:question-form="questionForm" :trial-clinical-id="trialClinicalId" @resetFormItemData="resetFormItemData"
|
||||
@setFormItemData="setFormItemData" />
|
||||
:question-form="questionForm" :trial-clinical-id="trialClinicalId" :SecondReviewState="SecondReviewState"
|
||||
@resetFormItemData="resetFormItemData" @setFormItemData="setFormItemData" />
|
||||
</template>
|
||||
</el-form>
|
||||
<div class="base-dialog-footer" v-if="!isViewer && openType !== 'look' && [2, 3].includes(clinicalDataLevel)"
|
||||
<div class="base-dialog-footer"
|
||||
v-if="!isViewer && openType !== 'look' && [2, 3].includes(clinicalDataLevel) && SecondReviewState <= 0"
|
||||
style="text-align:right;margin-top:10px;">
|
||||
<!-- 取消 -->
|
||||
<el-button size="small" type="primary" @click="close"
|
||||
@@ -55,6 +56,10 @@ export default {
|
||||
return 2
|
||||
}
|
||||
},
|
||||
SecondReviewState: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
openType: {
|
||||
type: String,
|
||||
},
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
<QuestionsForm v-if="clinicalUploadType === 2" :data="data" :trial-clinical-id="trialClinicalId"
|
||||
:is-viewer="isViewer" :visit-id="visitId" :subject-id="subjectId" :open-type="openType"
|
||||
:system-clinical-id="systemClinicalId" :trial-id="trialId" :reading-id="readingId"
|
||||
:clinical-form-id="clinicalFormId" :clinical-data-level="clinicalDataLevel" @close="close"></QuestionsForm>
|
||||
<uploadClinicalData v-else :subject-visit-id="subjectVisitId" :data="data" :enum-type="0" :allow-add-or-edit="true"
|
||||
@getList="() => { }">
|
||||
:clinical-form-id="clinicalFormId" :SecondReviewState="SecondReviewState" :clinical-data-level="clinicalDataLevel"
|
||||
@close="close"></QuestionsForm>
|
||||
<uploadClinicalData v-else :subject-visit-id="subjectVisitId" :SecondReviewState="SecondReviewState" :data="data"
|
||||
:enum-type="0" :allow-add-or-edit="true" @getList="() => { }">
|
||||
</uploadClinicalData>
|
||||
<div class="base-dialog-footer" v-if="!isViewer && openType !== 'look' && [0, 1].includes(clinicalDataLevel)"
|
||||
<div class="base-dialog-footer"
|
||||
v-if="!isViewer && openType !== 'look' && [0, 1].includes(clinicalDataLevel) && SecondReviewState <= 0"
|
||||
style="text-align:right;margin-top:10px;">
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" @click="submitClinicalForm">
|
||||
@@ -92,6 +94,10 @@ export default {
|
||||
type: String,
|
||||
default: () => ''
|
||||
},
|
||||
SecondReviewState: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
clinicalUploadType: {
|
||||
type: Number,
|
||||
default: () => {
|
||||
|
||||
@@ -24,8 +24,7 @@
|
||||
</div>
|
||||
<!--上传列表@selection-change="handleSelectionChange" @sort-change="handleSortByColumn"-->
|
||||
<el-table ref="dicomFilesTable" v-adaptive="{ bottomOffset: 85 }" height="100" :data="list" :loading="loading"
|
||||
class="dicomFiles-table"
|
||||
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
||||
class="dicomFiles-table" :default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
||||
<!-- <el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
@@ -35,9 +34,11 @@
|
||||
<!--受试者-->
|
||||
<el-table-column :label="$t('download:table:subjectCode')" min-width="130" prop="SubjectCode"
|
||||
show-overflow-tooltip />
|
||||
<!--访视名称-->
|
||||
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" sortable v-if="IsImageSegment" />
|
||||
<!--任务名称-->
|
||||
<el-table-column :label="$t('download:table:taskName')" min-width="130" show-overflow-tooltip prop="TaskBlindName"
|
||||
sortable />
|
||||
sortable v-else />
|
||||
<!--检查类型-->
|
||||
<el-table-column :label="$t('download:table:studyType')" min-width="130" show-overflow-tooltip prop="IsDicom"
|
||||
sortable>
|
||||
@@ -76,7 +77,8 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :modelList="modelList" :bodyPart="bodyPart"
|
||||
:IsDicom="IsDicom" :visitTaskId="modelTaskId" />
|
||||
:subjectVisitId="modelSubjectVisitId" :IsDicom="IsDicom" :isDownload="true" :visitTaskId="modelTaskId"
|
||||
:IsImageSegment="IsImageSegment" :Criterion="Criterion" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
@@ -127,6 +129,10 @@ export default {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
IsImageSegment: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -150,14 +156,16 @@ export default {
|
||||
open: null,
|
||||
downloadId: null,
|
||||
IsReadingTaskViewInOrder: 0, // 阅片规则
|
||||
bodyPart: [],
|
||||
bodyPart: {},
|
||||
modelTaskId: null,
|
||||
modelSubjectVisitId: null,
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.bodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.getList()
|
||||
this.bodyPart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.title = `Download Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
||||
if (this.IsImageSegment) this.title = `Download Images:${this.SubjectCode}`
|
||||
},
|
||||
beforeDestroy() {
|
||||
store.dispatch('trials/setUnLock', false)
|
||||
@@ -176,6 +184,12 @@ export default {
|
||||
if (this.TaskId) {
|
||||
this.searchData.VisitTaskId = this.TaskId
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
this.searchData.IsImageSegmentLabel = true
|
||||
}
|
||||
else if (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20) {
|
||||
this.searchData.IsImageSegmentLabel = false
|
||||
}
|
||||
this.loading = true
|
||||
let res = await getSubjectImageDownloadSelectList(this.searchData)
|
||||
this.loading = false
|
||||
@@ -258,6 +272,12 @@ export default {
|
||||
data.NoneDicomStudyIdList = [...data.NoneDicomStudyIdList, ...arr]
|
||||
}
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
data.IsImageSegmentLabel = true
|
||||
}
|
||||
else if (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20) {
|
||||
data.IsImageSegmentLabel = false
|
||||
}
|
||||
this.btnLoading = true
|
||||
let res = await getIRReadingDownloadStudyInfo(data)
|
||||
this.btnLoading = false
|
||||
@@ -287,35 +307,78 @@ export default {
|
||||
formatDownloadFile(list) {
|
||||
let files = [],
|
||||
name = `${list[0].SubjectCode}_${new Date().getTime()}.zip`
|
||||
if (this.IsReadingTaskViewInOrder === 1) {
|
||||
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
// name = `${list[0].TaskBlindName}.zip`
|
||||
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
|
||||
if (this.IsImageSegment) {
|
||||
name = `${list[0].SubjectCode}.zip`
|
||||
} else {
|
||||
if (this.IsReadingTaskViewInOrder === 1) {
|
||||
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
// name = `${list[0].TaskBlindName}.zip`
|
||||
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
|
||||
}
|
||||
}
|
||||
|
||||
list.forEach((data) => {
|
||||
if (data.StudyList && data.StudyList.length > 0) {
|
||||
let StudyList = data.StudyList
|
||||
StudyList.forEach((study) => {
|
||||
if (study.StudyDIRPath) {
|
||||
let obj = {
|
||||
name: `${data.SubjectCode}/${data.TaskBlindName
|
||||
}/${this.$fd('IsDicom', true)}/${study.StudyCode
|
||||
}/DICOMDIR`,
|
||||
url: this.OSSclientConfig.basePath + study.StudyDIRPath,
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
obj = {
|
||||
name: `${data.SubjectCode}/${data.VisitName
|
||||
}/${this.$fd('IsDicom', true)}/${study.StudyCode
|
||||
}/DICOMDIR`,
|
||||
url: this.OSSclientConfig.basePath + study.StudyDIRPath,
|
||||
}
|
||||
} else if (this.IsReadingTaskViewInOrder === 0) {
|
||||
obj = {
|
||||
name: `${data.TaskBlindName}/${this.$fd(
|
||||
'IsDicom',
|
||||
true
|
||||
)}/DICOMDIR`,
|
||||
url: this.OSSclientConfig.basePath + study.StudyDIRPath,
|
||||
}
|
||||
}
|
||||
files.push(obj)
|
||||
}
|
||||
if (study.SeriesList.length > 0) {
|
||||
study.SeriesList.forEach((series) => {
|
||||
if (series.InstancePathList.length > 0) {
|
||||
series.InstancePathList.forEach((instance) => {
|
||||
if (series.InstanceList.length > 0) {
|
||||
series.InstanceList.forEach((instance) => {
|
||||
let fileName = instance.Path.split('/').pop()
|
||||
if (instance.FileName) {
|
||||
fileName = instance.FileName
|
||||
}
|
||||
let obj = {
|
||||
name: `${data.SubjectCode}/${data.TaskBlindName
|
||||
}/${this.$fd('IsDicom', true)}/${study.StudyCode
|
||||
}/${fileName}`,
|
||||
}/IMAGE/${fileName}`,
|
||||
url: this.OSSclientConfig.basePath + instance.Path,
|
||||
IsEncapsulated: instance.IsEncapsulated
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
if (this.IsImageSegment) {
|
||||
obj = {
|
||||
name: `${data.SubjectCode}/${data.VisitName
|
||||
}/${this.$fd('IsDicom', true)}/${study.StudyCode
|
||||
}/IMAGE/${fileName}`,
|
||||
url: this.OSSclientConfig.basePath + instance.Path,
|
||||
IsEncapsulated: instance.IsEncapsulated
|
||||
}
|
||||
} else if (this.IsReadingTaskViewInOrder === 0) {
|
||||
obj = {
|
||||
name: `${data.TaskBlindName}/${this.$fd(
|
||||
'IsDicom',
|
||||
true
|
||||
)}/${fileName}`,
|
||||
)}/IMAGE/${fileName}`,
|
||||
url: this.OSSclientConfig.basePath + instance.Path,
|
||||
IsEncapsulated: instance.IsEncapsulated
|
||||
}
|
||||
}
|
||||
files.push(obj)
|
||||
@@ -338,7 +401,16 @@ export default {
|
||||
)}/${study.StudyCode}/${item.FileName}`,
|
||||
url: this.OSSclientConfig.basePath + item.Path,
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
if (this.IsImageSegment) {
|
||||
obj = {
|
||||
name: `${data.SubjectCode}/${data.VisitName}/${this.$fd(
|
||||
'IsDicom',
|
||||
false
|
||||
)}/${study.StudyCode}/${item.FileName}`,
|
||||
url: this.OSSclientConfig.basePath + item.Path,
|
||||
}
|
||||
}
|
||||
else if (this.IsReadingTaskViewInOrder === 0) {
|
||||
obj = {
|
||||
name: `${data.TaskBlindName}/${this.$fd(
|
||||
'IsDicom',
|
||||
@@ -368,6 +440,9 @@ export default {
|
||||
},
|
||||
handleOpenDialog(item) {
|
||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.TaskBlindName}`
|
||||
if (this.IsImageSegment) {
|
||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.VisitName}`
|
||||
}
|
||||
if (item.IsDicom) {
|
||||
this.modelList = item.DicomStudyList
|
||||
} else {
|
||||
@@ -377,6 +452,7 @@ export default {
|
||||
})
|
||||
}
|
||||
this.modelTaskId = item.VisitTaskId
|
||||
this.modelSubjectVisitId = item.SourceSubjectVisitId
|
||||
this.IsDicom = item.IsDicom
|
||||
this.model_cfg.visible = true
|
||||
},
|
||||
@@ -405,9 +481,16 @@ export default {
|
||||
}
|
||||
let trialId = this.$route.query.trialId
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}`,
|
||||
})
|
||||
let routeData = null
|
||||
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true`,
|
||||
})
|
||||
} else {
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true`,
|
||||
})
|
||||
}
|
||||
this.open = window.open(routeData.href, '_blank')
|
||||
},
|
||||
// 预览阅片影像
|
||||
|
||||
@@ -283,6 +283,7 @@ export default {
|
||||
}
|
||||
if (this.visitTaskId) {
|
||||
this.form.VisitTaskId = this.visitTaskId
|
||||
this.form.QuestionType = 6
|
||||
}
|
||||
if (this.SubjectVisitId) {
|
||||
this.form.SubjectVisitId = this.SubjectVisitId
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<div :id="key" class="readingChart" v-show="visible" :style="{
|
||||
'z-index': zIndex
|
||||
}">
|
||||
<div ref="chartContainer" style="width: 490px; height: 290px;" v-loading="loading"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { getReportsChartData } from "@/api/reading"
|
||||
import moment from "moment"
|
||||
let echarts = require('echarts/lib/echarts');
|
||||
|
||||
// 按需引入图表
|
||||
// require('echarts/lib/chart/bar');
|
||||
require('echarts/lib/chart/line');
|
||||
// require('echarts/lib/chart/pie');
|
||||
// require('echarts/lib/chart/scatter');
|
||||
|
||||
// 按需引入组件
|
||||
require('echarts/lib/component/tooltip');
|
||||
require('echarts/lib/component/title');
|
||||
require('echarts/lib/component/legend');
|
||||
require('echarts/lib/component/grid');
|
||||
require('echarts/lib/component/dataZoom');
|
||||
export default {
|
||||
name: "readingChart",
|
||||
props: {
|
||||
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
visible: false,
|
||||
zIndex: 9,
|
||||
chart: null,
|
||||
loading: false,
|
||||
key: 'readingChart'
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
init(event, obj, zIndex = 9) {
|
||||
this.loading = true
|
||||
this.zIndex = zIndex
|
||||
let { key } = obj
|
||||
if (key) {
|
||||
this.key = key
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.visible = true
|
||||
let readingChart = document.querySelector(`#${this.key}`);
|
||||
let chaY = document.body.clientHeight - event.clientY;
|
||||
let chaX = document.body.clientWidth - event.clientX;
|
||||
if (chaY < 250) {
|
||||
readingChart.style.top = event.clientY - 220 + "px";
|
||||
} else {
|
||||
readingChart.style.top = event.clientY + "px";
|
||||
}
|
||||
if (chaX < 500) {
|
||||
readingChart.style.left = event.clientX - 520 + "px";
|
||||
} else {
|
||||
readingChart.style.left = event.clientX + 15 + "px";
|
||||
}
|
||||
this.getInfo(obj)
|
||||
})
|
||||
},
|
||||
async getInfo(data) {
|
||||
try {
|
||||
let { VisitTaskId = null, TrialId = null, QuestionId = null, QuestionName = null, TableQuestionId = null, RowIndex = null, ReportChartTypeEnum = null } = data
|
||||
let params = {
|
||||
VisitTaskId, TrialId, QuestionId, TableQuestionId, RowIndex, ReportChartTypeEnum
|
||||
}
|
||||
this.loading = true
|
||||
let res = await getReportsChartData(params)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
let LatestScanDateList = res.Result.LatestScanDateList.map(item => item.split(" ")[0])
|
||||
let obj = {
|
||||
title: QuestionName,
|
||||
xAxisData: LatestScanDateList || [],
|
||||
series: [],
|
||||
unit: this.$fd("ValueUnit", res.Result.Unit),
|
||||
visitName: res.Result.VisitTaskNameList,
|
||||
min: null,
|
||||
max: null
|
||||
}
|
||||
res.Result.ChartDataList.forEach((item) => {
|
||||
let arr = []
|
||||
item.Value.forEach((d, index) => {
|
||||
// arr.push([LatestScanDateList[index], d])
|
||||
arr.push(d)
|
||||
})
|
||||
obj.series.push({
|
||||
name: item.Name,
|
||||
data: arr,
|
||||
type: 'line'
|
||||
})
|
||||
});
|
||||
// if (Array.isArray(res.Result.LatestScanDateList) && res.Result.LatestScanDateList.length >= 2) {
|
||||
// let hours = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'hours');
|
||||
// let days = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'days');
|
||||
// let months = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).diff(moment(res.Result.LatestScanDateList[0]), 'months');
|
||||
// console.log(hours, 'hours')
|
||||
// console.log(days, 'days')
|
||||
// console.log(months, 'months')
|
||||
// if (hours < 24) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// if (days >= 1 && days <= 7) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(7, 'days').format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// if (days > 7 && days < 30) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[0]).endOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// if (months >= 1 && months <= 3) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(4, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// if (months > 3 && months <= 6) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(7, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// if (months > 6 && months <= 12) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[0]).add(13, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// if (months > 12) {
|
||||
// obj.min = moment(res.Result.LatestScanDateList[0]).startOf('month').format('YYYY-MM-DD') + ' 00:00:00'
|
||||
// obj.max = moment(res.Result.LatestScanDateList[res.Result.LatestScanDateList.length - 1]).add(1, 'months').startOf('month').format('YYYY-MM-DD') + ' 23:59:59'
|
||||
// }
|
||||
// }
|
||||
// console.log(obj)
|
||||
this.initChart(obj)
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
foo() {
|
||||
this.visible = false
|
||||
this.$emit("foo");
|
||||
this.dispose()
|
||||
},
|
||||
initChart(obj) {
|
||||
this.chart = echarts.init(this.$refs.chartContainer);
|
||||
// ...图表配置
|
||||
const option = {
|
||||
title: {
|
||||
text: obj.title,
|
||||
textStyle: {
|
||||
color: "#fff"
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
// formatter: function (params) {
|
||||
// let index = obj.xAxisData.findIndex(item => item === params[0].value[0])
|
||||
// let result = obj.visitName[index] + ' ' + params[0].value[0] + '<br>'; // 显示类目名(如日期)
|
||||
// params.forEach(function (item) {
|
||||
// result += item.marker + ' ' + item.seriesName + ': ' + item.value[1] + '<br>'; // 显示每个系列的图例、系列名和值
|
||||
// });
|
||||
// return result;
|
||||
// }
|
||||
},
|
||||
xAxis: {
|
||||
// type: 'time',
|
||||
// data: obj.xAxisData,
|
||||
data: obj.visitName,
|
||||
axisLine: { // 设置 x 轴线颜色
|
||||
lineStyle: {
|
||||
color: '#fff',
|
||||
}
|
||||
},
|
||||
axisLabel: { // 设置 x 轴文字颜色
|
||||
textStyle: {
|
||||
color: '#fff'
|
||||
}
|
||||
},
|
||||
// splitLine: {
|
||||
// show: false // 隐藏网格线
|
||||
// },
|
||||
// min: obj.min,
|
||||
// max: obj.max
|
||||
},
|
||||
yAxis: {
|
||||
name: obj.unit,
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
}
|
||||
},
|
||||
axisLine: {
|
||||
lineStyle: {
|
||||
color: '#fff',
|
||||
}
|
||||
},
|
||||
},
|
||||
series: obj.series
|
||||
};
|
||||
// 4. 使用配置项渲染图表
|
||||
this.chart.setOption(option);
|
||||
},
|
||||
resize() {
|
||||
if (this.chart) {
|
||||
this.chart.resize()
|
||||
}
|
||||
},
|
||||
dispose() {
|
||||
if (this.chart) {
|
||||
this.chart.dispose()
|
||||
this.chart = null
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.readingChart {
|
||||
min-width: 500px;
|
||||
max-width: 500px;
|
||||
font-size: 14px;
|
||||
display: inline-block;
|
||||
background: #000;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
position: fixed;
|
||||
padding: 10px 6px;
|
||||
list-style-type: none;
|
||||
min-height: 300px;
|
||||
max-height: 80vh;
|
||||
// overflow: hidden;
|
||||
// overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -10,9 +10,11 @@
|
||||
<!--检查列表-->
|
||||
<el-table :data="list" style="width: 100%" height="300" :loading="loading">
|
||||
<!--受试者-->
|
||||
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" />
|
||||
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" sortable />
|
||||
<!--访视名称-->
|
||||
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" v-if="IsImageSegment" sortable />
|
||||
<!--任务名称-->
|
||||
<el-table-column prop="TaskBlindName" :label="$t('upload:dicom:table:taskBlindName')" />
|
||||
<el-table-column prop="TaskBlindName" :label="$t('upload:dicom:table:taskBlindName')" v-else sortable />
|
||||
<!--原始检查数-->
|
||||
<el-table-column prop="OrginalStudyList" :label="$t('upload:dicom:table:orginalStudyListNum')">
|
||||
<template slot-scope="scope">
|
||||
@@ -299,7 +301,8 @@
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :IsDicom="true" :bodyPart="bodyPart"
|
||||
:modelList="modelList" :isUpload="openIsUpload" :TrialModality="TrialModality" @getList="getList" />
|
||||
:subjectVisitId="openSubjectVisitId" :modelList="modelList" :isUpload="openIsUpload"
|
||||
:visitTaskId="openVisitTaskId" :TrialModality="TrialModality" @getList="getList" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -363,12 +366,17 @@ export default {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
IsImageSegment: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
components: {
|
||||
'study-view': studyView,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
list: [],
|
||||
StudyInstanceUidList: [],
|
||||
SopInstanceUidList: [],
|
||||
@@ -406,17 +414,17 @@ export default {
|
||||
subjectVisitId: null,
|
||||
errStudyUidList: [],
|
||||
open: null,
|
||||
bodyPart: [],
|
||||
bodyPart: {},
|
||||
openIsUpload: false,
|
||||
openSubjectVisitId: null,
|
||||
openVisitTaskId: null,
|
||||
TrialModality: [],
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
async mounted() {
|
||||
this.trialId = this.$route.query.trialId
|
||||
this.bodyPart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.bodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.getList()
|
||||
this.uploadQueues = []
|
||||
this.OSSclient.close()
|
||||
},
|
||||
@@ -441,6 +449,12 @@ export default {
|
||||
if (this.TaskId) {
|
||||
params.VisitTaskId = this.TaskId
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
params.IsImageSegmentLabel = true
|
||||
}
|
||||
else if (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20) {
|
||||
params.IsImageSegmentLabel = false
|
||||
}
|
||||
this.loading = true
|
||||
let res = await getSubjectImageUploadList(params)
|
||||
this.loading = false
|
||||
@@ -456,7 +470,7 @@ export default {
|
||||
data.SubjectId = item.SubejctId
|
||||
data.VisitTaskId = item.VisitTaskId
|
||||
data.SourceSubjectVisitId = item.SourceSubjectVisitId
|
||||
this.subjectVisitId = item.SourceSubjectVisitId
|
||||
// this.subjectVisitId = item.SourceSubjectVisitId
|
||||
this.StudyInstanceUidList.push(data)
|
||||
})
|
||||
}
|
||||
@@ -490,6 +504,7 @@ export default {
|
||||
if (confirm !== 'confirm') return
|
||||
let params = {
|
||||
VisitTaskId: item.VisitTaskId,
|
||||
SubjectVisitId: item.SourceSubjectVisitId || item.SubjectVisitId,
|
||||
IsDicom: true,
|
||||
}
|
||||
let res = await deleteTaskStudy(params)
|
||||
@@ -522,7 +537,9 @@ export default {
|
||||
// 打开弹窗
|
||||
handleOpenDialog(item, list, isUpload = false) {
|
||||
this.openIsUpload = isUpload
|
||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.TaskBlindName}`
|
||||
this.openSubjectVisitId = item.SubjectVisitId || item.SourceSubjectVisitId
|
||||
this.openVisitTaskId = item.VisitTaskId
|
||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${this.IsImageSegment ? item.VisitName : item.TaskBlindName}`
|
||||
this.modelList = item[list]
|
||||
this.model_cfg.visible = true
|
||||
},
|
||||
@@ -538,6 +555,9 @@ export default {
|
||||
if (this.VisitTaskId) {
|
||||
data.VisitTaskId = this.VisitTaskId
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
data.IsImageSegmentLabel = true
|
||||
}
|
||||
let res = await verifyIRStudyAllowUpload(data)
|
||||
if (res.IsSuccess) {
|
||||
return res.Result
|
||||
@@ -564,8 +584,9 @@ export default {
|
||||
confirmMessage = null
|
||||
for (let i = 0; i < checkFiles.length; i++) {
|
||||
let item = checkFiles[i]
|
||||
var dicom = await parseDicom(item, 'StudyInstanceUid')
|
||||
var dicom = await parseDicom(item, ['StudyInstanceUid', 'Modality'])
|
||||
if (!dicom.StudyInstanceUid) continue
|
||||
if (this.IsImageSegment && dicom.Modality !== 'IVUS') continue
|
||||
let has = true,
|
||||
has2 = false,
|
||||
has3 = false
|
||||
@@ -619,8 +640,8 @@ export default {
|
||||
if (this.errStudyUidList && this.errStudyUidList.length > 0) {
|
||||
for (let i = 0; i < checkFiles.length; i++) {
|
||||
let item = checkFiles[i]
|
||||
var dicom = await parseDicom(item, 'StudyInstanceUid')
|
||||
if (!!~this.errStudyUidList.indexOf(dicom.StudyInstanceUid)) {
|
||||
var dicom = await parseDicom(item, ['StudyInstanceUid', 'Modality'])
|
||||
if (!!~this.errStudyUidList.indexOf(dicom.StudyInstanceUid) || (this.IsImageSegment && dicom.Modality !== 'IVUS')) {
|
||||
this.hasOtherStudy = true
|
||||
checkFiles.splice(i, 1)
|
||||
i--
|
||||
@@ -646,6 +667,7 @@ export default {
|
||||
resolve()
|
||||
})
|
||||
var validFilesCount = 0
|
||||
scope.uploadQueues = []
|
||||
for (var i = 0; i < checkFiles.length; ++i) {
|
||||
; (function (index) {
|
||||
p = p.then(function () {
|
||||
@@ -731,6 +753,8 @@ export default {
|
||||
fileList: [],
|
||||
dicomInfo: {
|
||||
studyId: data.string('x00200010'),
|
||||
DicomStudyDate: data.string('x00080020'),
|
||||
DicomStudyTime: data.string('x00080030'),
|
||||
studyUid: studyUid,
|
||||
patientId: data.string('x00100020'),
|
||||
patientName: patientNameStr,
|
||||
@@ -841,6 +865,8 @@ export default {
|
||||
)
|
||||
seriesItem = {
|
||||
seriesUid: seriesUid,
|
||||
DicomSeriesDate: data.string('x00080021'),
|
||||
DicomSeriesTime: data.string('x00080031'),
|
||||
seriesNumber: data.intString('x00200011') || 1,
|
||||
modality: data.string('x00080060') || '',
|
||||
description: seriesDescriptionStr,
|
||||
@@ -880,6 +906,10 @@ export default {
|
||||
}
|
||||
instanceItem = {
|
||||
instanceUid: instanceUid,
|
||||
SOPClassUID: data.string('x00080016'),
|
||||
TransferSytaxUID: data.string('x00020010'),
|
||||
MediaStorageSOPInstanceUID: instanceUid,
|
||||
MediaStorageSOPClassUID: data.string('x00080016'),
|
||||
instanceNumber: data.intString('x00200013') || 1,
|
||||
frameCount: data.intString('x00280008') || 1,
|
||||
instanceTime: instanceTime,
|
||||
@@ -887,7 +917,7 @@ export default {
|
||||
imageColumns: data.uint16('x00280011') || 0,
|
||||
sliceLocation: data.intString('x00201041') || 0,
|
||||
sliceThickness: data.string('x00180050') || '',
|
||||
numberOfFrames: data.intString('x00280008') || 0,
|
||||
numberOfFrames: data.intString('x00280008') || 1,
|
||||
pixelSpacing: data.string('x00280030') || '',
|
||||
imagerPixelSpacing: data.string('x00181164') || '',
|
||||
frameOfReferenceUID: data.string('x00200052') || '',
|
||||
@@ -1027,10 +1057,25 @@ export default {
|
||||
var scope = this
|
||||
return new Promise(function (resolve, reject) {
|
||||
try {
|
||||
let subjectVisitId = null;
|
||||
if (scope.VisitTaskId) {
|
||||
scope.StudyInstanceUidList.forEach(item => {
|
||||
if (item.VisitTaskId === scope.VisitTaskId) {
|
||||
subjectVisitId = item.SourceSubjectVisitId
|
||||
}
|
||||
})
|
||||
} else {
|
||||
scope.StudyInstanceUidList.forEach(item => {
|
||||
if (item.StudyInstanceUid === scope.uploadQueues[index].dicomInfo.studyUid) {
|
||||
subjectVisitId = item.SourceSubjectVisitId
|
||||
}
|
||||
})
|
||||
}
|
||||
if (!subjectVisitId) return reject('subjectVisitId is notFind')
|
||||
preArchiveDicomStudy({
|
||||
trialId: scope.trialId,
|
||||
subjectId: scope.SubjectId,
|
||||
subjectVisitId: scope.subjectVisitId,
|
||||
subjectVisitId: subjectVisitId,
|
||||
fileSize: scope.uploadQueues[index].dicomInfo.fileSize,
|
||||
fileCount: scope.uploadQueues[index].dicomInfo.fileCount,
|
||||
IsDicomReUpload:
|
||||
@@ -1046,7 +1091,7 @@ export default {
|
||||
dicomInfo.seriesNum = seriesNum
|
||||
dicomInfo.fileNum = fileNum
|
||||
dicomInfo.subjectId = scope.SubjectId
|
||||
dicomInfo.subjectVisitId = scope.subjectVisitId
|
||||
dicomInfo.subjectVisitId = subjectVisitId
|
||||
let t = setInterval(() => {
|
||||
dicomUploadInProgress({
|
||||
trialId: scope.trialId,
|
||||
@@ -1066,7 +1111,7 @@ export default {
|
||||
let params = {
|
||||
trialId: scope.trialId,
|
||||
subjectId: scope.SubjectId,
|
||||
subjectVisitId: scope.subjectVisitId,
|
||||
subjectVisitId: subjectVisitId,
|
||||
studyMonitorId: res.Result,
|
||||
failedFileCount: 0,
|
||||
RecordPath: null,
|
||||
@@ -1088,6 +1133,8 @@ export default {
|
||||
acquisitionNumber: dicomInfo.acquisitionNumber,
|
||||
triggerTime: dicomInfo.triggerTime,
|
||||
bodyPartExamined: '',
|
||||
DicomStudyDate: dicomInfo.DicomStudyDate,
|
||||
DicomStudyTime: dicomInfo.DicomStudyTime,
|
||||
seriesList: [],
|
||||
},
|
||||
}
|
||||
@@ -1112,6 +1159,10 @@ export default {
|
||||
instanceList.push({
|
||||
studyInstanceUid: dicomInfo.studyUid,
|
||||
seriesInstanceUid: v.seriesUid,
|
||||
SOPClassUID: o.SOPClassUID,
|
||||
TransferSytaxUID: o.TransferSytaxUID,
|
||||
MediaStorageSOPInstanceUID: o.MediaStorageSOPInstanceUID,
|
||||
MediaStorageSOPClassUID: o.MediaStorageSOPClassUID,
|
||||
sopInstanceUid: o.instanceUid,
|
||||
instanceNumber: o.instanceNumber,
|
||||
instanceTime: o.instanceTime,
|
||||
@@ -1140,6 +1191,16 @@ export default {
|
||||
o.instanceUid +
|
||||
params.trialId
|
||||
)}`
|
||||
if (scope.IsImageSegment) {
|
||||
path = `/${params.trialId}/Image/${params.subjectId
|
||||
}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId
|
||||
}/${scope.getGuid(
|
||||
dicomInfo.studyUid +
|
||||
v.seriesUid +
|
||||
o.instanceUid +
|
||||
params.trialId
|
||||
)}`
|
||||
}
|
||||
if (scope.isClose) return
|
||||
let res = await dcmUpload(
|
||||
{
|
||||
@@ -1173,6 +1234,9 @@ export default {
|
||||
o.imageRows
|
||||
)
|
||||
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||
if (scope.IsImageSegment) {
|
||||
thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||
}
|
||||
let OSSclient = scope.OSSclient
|
||||
let seriesRes = await OSSclient.put(
|
||||
thumbnailPath,
|
||||
@@ -1193,6 +1257,10 @@ export default {
|
||||
studyInstanceUid: dicomInfo.studyUid,
|
||||
seriesInstanceUid: v.seriesUid,
|
||||
sopInstanceUid: o.instanceUid,
|
||||
SOPClassUID: o.SOPClassUID,
|
||||
TransferSytaxUID: o.TransferSytaxUID,
|
||||
MediaStorageSOPInstanceUID: o.MediaStorageSOPInstanceUID,
|
||||
MediaStorageSOPClassUID: o.MediaStorageSOPClassUID,
|
||||
instanceNumber: o.instanceNumber,
|
||||
instanceTime: o.instanceTime,
|
||||
imageRows: o.imageRows,
|
||||
@@ -1238,6 +1306,8 @@ export default {
|
||||
seriesInstanceUid: v.seriesUid,
|
||||
seriesNumber: v.seriesNumber,
|
||||
seriesTime: v.seriesTime,
|
||||
DicomSeriesDate: v.DicomSeriesDate,
|
||||
DicomSeriesTime: v.DicomSeriesTime,
|
||||
sliceThickness: v.sliceThickness,
|
||||
imagePositionPatient: v.imagePositionPatient,
|
||||
imageOrientationPatient: v.imageOrientationPatient,
|
||||
@@ -1258,6 +1328,9 @@ export default {
|
||||
let text = JSON.stringify(Record)
|
||||
let logJsonBlob = scope.generateTxtFile(text)
|
||||
let logJsonObjectName = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${params.studyMonitorId}.txt`
|
||||
if (scope.IsImageSegment) {
|
||||
logJsonObjectName = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.visitTaskId}/${dicomInfo.studyUid}/${params.studyMonitorId}.txt`
|
||||
}
|
||||
let logRes
|
||||
try {
|
||||
logRes = await scope.OSSclient.put(
|
||||
@@ -1286,6 +1359,9 @@ export default {
|
||||
v.instanceList[0].imageRows
|
||||
)
|
||||
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||
if (scope.IsImageSegment) {
|
||||
thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/AnnotationImage/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||
}
|
||||
let OSSclient = scope.OSSclient
|
||||
try {
|
||||
let seriesRes = await OSSclient.put(thumbnailPath, blob)
|
||||
@@ -1303,6 +1379,9 @@ export default {
|
||||
if (scope.isClose) return false
|
||||
console.log(params)
|
||||
params.VisitTaskId = dicomInfo.visitTaskId
|
||||
if (scope.IsImageSegment) {
|
||||
params.IsImageSegmentLabel = true
|
||||
}
|
||||
addOrUpdateArchiveTaskStudy(params)
|
||||
.then((res) => {
|
||||
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
||||
@@ -1397,7 +1476,7 @@ export default {
|
||||
var token = getToken()
|
||||
let trialId = this.$route.query.trialId
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/showvisitdicoms?page=upload&trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}`,
|
||||
path: `/showvisitdicoms?page=upload&trialId=${trialId}&visitTaskId=${this.IsImageSegment ? 'undefined' : row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}`,
|
||||
})
|
||||
this.open = window.open(routeData.href, '_blank')
|
||||
},
|
||||
|
||||
@@ -1,40 +1,17 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible.sync="visible"
|
||||
:fullscreen="true"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="beforeClose"
|
||||
:append-to-body="true"
|
||||
class="uploadDicomAndNonedicom"
|
||||
>
|
||||
<el-dialog :visible.sync="visible" :fullscreen="true" :close-on-click-modal="false" :before-close="beforeClose"
|
||||
:append-to-body="true" class="uploadDicomAndNonedicom">
|
||||
<span slot="title">{{ title }}</span>
|
||||
<el-tabs type="border-card" v-model="activeName">
|
||||
<el-tab-pane
|
||||
:label="$t('uploadDicomAndNonedicom:label:dicom')"
|
||||
name="dicom"
|
||||
>
|
||||
<dicomFile
|
||||
v-if="activeName === 'dicom'"
|
||||
:SubjectId="SubjectId"
|
||||
:SubjectCode="SubjectCode"
|
||||
:Criterion="Criterion"
|
||||
:TaskId="VisitTaskId"
|
||||
:isUpload.sync="isUpload"
|
||||
:isReadingTaskViewInOrder="isReadingTaskViewInOrder"
|
||||
/>
|
||||
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:dicom')" name="dicom">
|
||||
<dicomFile v-if="activeName === 'dicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
|
||||
:Criterion="Criterion" :TaskId="VisitTaskId" :isUpload.sync="isUpload"
|
||||
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :IsImageSegment="IsImageSegment" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
:label="$t('uploadDicomAndNonedicom:label:nonedicom')"
|
||||
name="nonedicom"
|
||||
>
|
||||
<nonedicomFile
|
||||
v-if="activeName === 'nonedicom'"
|
||||
:SubjectId="SubjectId"
|
||||
:SubjectCode="SubjectCode"
|
||||
:Criterion="Criterion"
|
||||
:VisitTaskId="VisitTaskId"
|
||||
:isUpload.sync="isUpload"
|
||||
/>
|
||||
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:nonedicom')" name="nonedicom">
|
||||
<nonedicomFile v-if="activeName === 'nonedicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
|
||||
:Criterion="Criterion" :VisitTaskId="VisitTaskId" :isUpload.sync="isUpload"
|
||||
:IsImageSegment="IsImageSegment" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
@@ -74,6 +51,10 @@ export default {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
IsImageSegment: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -84,6 +65,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.title = `Upload Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
||||
if (this.IsImageSegment) this.title = `Upload Images:${this.SubjectCode}`
|
||||
store.dispatch('trials/setUnLock', true)
|
||||
},
|
||||
methods: {
|
||||
@@ -103,11 +85,13 @@ export default {
|
||||
::v-deep.el-tabs--left .el-tabs__header.is-left {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.uploadDicomAndNonedicom {
|
||||
::v-deep.el-tabs--border-card > .el-tabs__header .el-tabs__item {
|
||||
::v-deep.el-tabs--border-card>.el-tabs__header .el-tabs__item {
|
||||
color: #909399;
|
||||
}
|
||||
::v-deep.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
|
||||
|
||||
::v-deep.el-tabs--border-card>.el-tabs__header .el-tabs__item.is-active {
|
||||
color: #428bca;
|
||||
background-color: #fff;
|
||||
border-right-color: #dcdfe6;
|
||||
|
||||
@@ -4,21 +4,31 @@
|
||||
<span>{{ $t('upload:nonedicom:title') }}</span>
|
||||
<div class="tip">
|
||||
<i class="el-icon-warning-outline"></i>
|
||||
<div v-html="$t('upload:nonedicom:tip:message')"></div>
|
||||
<div v-html="$t('upload:nonedicom:tip:message').replace(
|
||||
'xxx',
|
||||
relationInfo.ImageFormatList.join('、')
|
||||
)"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!--检查列表-->
|
||||
<!--检查列表 @sort-change="handleSortByColumn"-->
|
||||
<el-table :data="list" style="width: 100%" v-adaptive="{ bottomOffset: 60 }" :loading="loading"
|
||||
@sort-change="handleSortByColumn" :default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
||||
<!--受试者-->
|
||||
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
|
||||
<!--受试者 sortable="custom"-->
|
||||
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')" />
|
||||
<!--访视名称-->
|
||||
<el-table-column prop="VisitName" :label="$t('upload:nonedicom:table:VisitName')" sortable
|
||||
v-if="IsImageSegment" />
|
||||
<!--任务名称-->
|
||||
<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 v-else />
|
||||
<!--检查类型-->
|
||||
<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>
|
||||
</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>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ getBodyPart(scope.row.BodyPart, scope.row.BodyPartForEditOther) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--原文件数-->
|
||||
<el-table-column prop="FileCount" :label="$t('upload:nonedicom:table:fileCount')">
|
||||
<template slot-scope="scope">
|
||||
@@ -124,7 +134,10 @@
|
||||
<!-- 多文件上传 -->
|
||||
<form id="inputForm" ref="uploadForm">
|
||||
<el-divider content-position="left">{{
|
||||
$t('trials:uploadNonDicoms:label:fileType')
|
||||
$t('trials:uploadNonDicoms:label:fileType').replace(
|
||||
'xxx',
|
||||
relationInfo.ImageFormatList.join('、')
|
||||
)
|
||||
}}</el-divider>
|
||||
<div class="form-group">
|
||||
<div class="upload" style="margin-right: 10px">
|
||||
@@ -215,8 +228,8 @@ let defaultSearchData = () => {
|
||||
SubjectId: null,
|
||||
TrialReadingCriterionId: null,
|
||||
SubjectCode: null,
|
||||
Asc: false,
|
||||
SortField: 'TaskBlindName',
|
||||
// Asc: false,
|
||||
// SortField: 'TaskBlindName',
|
||||
}
|
||||
}
|
||||
export default {
|
||||
@@ -244,6 +257,10 @@ export default {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
IsImageSegment: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -262,6 +279,10 @@ export default {
|
||||
currentRow: {},
|
||||
studyMonitorId: null,
|
||||
open: null,
|
||||
BodyPart: {},
|
||||
relationInfo: {
|
||||
ImageFormatList: []
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -289,7 +310,8 @@ export default {
|
||||
store.dispatch('trials/setUnLock', this.btnLoading)
|
||||
},
|
||||
},
|
||||
created() {
|
||||
async created() {
|
||||
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.getList()
|
||||
},
|
||||
beforeDestroy() {
|
||||
@@ -305,11 +327,22 @@ export default {
|
||||
if (this.VisitTaskId) {
|
||||
this.searchData.VisitTaskId = this.VisitTaskId
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
this.searchData.IsImageSegmentLabel = true
|
||||
}
|
||||
else if (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20) {
|
||||
this.searchData.IsImageSegmentLabel = false
|
||||
}
|
||||
this.loading = true
|
||||
let res = await getIRUploadTaskNoneDicomStudyList(this.searchData)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.list = res.Result
|
||||
this.relationInfo = res.OtherInfo
|
||||
this.faccept = []
|
||||
this.relationInfo.ImageFormatList.forEach((item) => {
|
||||
this.faccept.push(`.${item}`)
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
@@ -473,16 +506,16 @@ export default {
|
||||
}
|
||||
},
|
||||
// 排序
|
||||
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()
|
||||
},
|
||||
// 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()
|
||||
// },
|
||||
// 获取待上传文件信息
|
||||
handleSelectionChange(selection) {
|
||||
this.selectArr = selection
|
||||
@@ -528,9 +561,15 @@ export default {
|
||||
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
||||
file.status = 1
|
||||
let path = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId
|
||||
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
|
||||
}/${this.currentRow.SourceSubjectVisitId}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
|
||||
.substring(file.name.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()}`
|
||||
if (this.IsImageSegment) {
|
||||
path = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId
|
||||
}/${this.currentRow.SourceSubjectVisitId}/AnnotationImage/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
|
||||
.substring(file.name.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()}`
|
||||
}
|
||||
file.curPath = path
|
||||
const fileData = await this.fileToBlob(file.file)
|
||||
let res = await this.fileToOss(path, fileData, file)
|
||||
@@ -614,6 +653,9 @@ export default {
|
||||
params.RecordPath = RecordPath.path
|
||||
params.FailedFileCount = RecordPath.Record.Failed.length
|
||||
}
|
||||
if (this.IsImageSegment) {
|
||||
params.IsImageSegmentLabel = true
|
||||
}
|
||||
uploadNoneDicomFile(params)
|
||||
.then((res) => {
|
||||
if (!isReLoad) {
|
||||
@@ -652,7 +694,10 @@ export default {
|
||||
})
|
||||
let text = JSON.stringify(Record)
|
||||
let logJsonBlob = this.generateTxtFile(text)
|
||||
let logJsonObjectName = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId}/${this.currentRow.VisitTaskId}/${this.studyMonitorId}.txt`
|
||||
let logJsonObjectName = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId}/${this.currentRow.SourceSubjectVisitId}/${this.currentRow.VisitTaskId}/${this.studyMonitorId}.txt`
|
||||
if (this.IsImageSegment) {
|
||||
logJsonObjectName = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId}/${this.currentRow.SourceSubjectVisitId}/AnnotationImage/${this.currentRow.VisitTaskId}/${this.studyMonitorId}.txt`
|
||||
}
|
||||
let logRes
|
||||
try {
|
||||
logRes = await this.OSSclient.put(logJsonObjectName, logJsonBlob)
|
||||
@@ -674,6 +719,26 @@ export default {
|
||||
let blob = new Blob(['\ufeff', text], { type: 'text/plain' })
|
||||
return blob
|
||||
},
|
||||
getBodyPart(bodyPart, other) {
|
||||
if (!bodyPart && !other) return ''
|
||||
var separator = ','
|
||||
if (bodyPart.indexOf('|') > -1) {
|
||||
separator = '|'
|
||||
} else if (bodyPart.indexOf(',') > -1) {
|
||||
separator = ','
|
||||
} else if (bodyPart.indexOf(',') > -1) {
|
||||
separator = ','
|
||||
}
|
||||
var arr = bodyPart.split(separator)
|
||||
var newArr = arr.map((i) => {
|
||||
return this.$fd('Bodypart', i.trim(), 'Code', this.BodyPart, 'Name')
|
||||
})
|
||||
if (other) {
|
||||
newArr.push(other)
|
||||
}
|
||||
newArr = newArr.filter(Boolean)
|
||||
return newArr.join(' | ')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -2,120 +2,54 @@
|
||||
<div v-if="model_cfg.visible">
|
||||
<base-model :config="model_cfg">
|
||||
<div slot="dialog-body">
|
||||
<el-button v-if="!isUpload && !isDownload" type='primary' size="small" style="float:right;" @click="preview">
|
||||
{{ $t("common:button:preview") }}
|
||||
</el-button>
|
||||
<el-table :data="modelList" style="width: 100%" height="300">
|
||||
<!--检查编号-->
|
||||
<el-table-column
|
||||
prop="StudyCode"
|
||||
:label="$t('trials:uploadImage:table:StudyCode')"
|
||||
/>
|
||||
<el-table-column prop="StudyCode" :label="$t('trials:uploadImage:table:StudyCode')" />
|
||||
<!--检查类型-->
|
||||
<el-table-column
|
||||
prop="ModalityForEdit"
|
||||
:label="$t('trials:uploadImage:table:ModalityForEdit')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<el-table-column prop="ModalityForEdit" :label="$t('trials:uploadImage:table:ModalityForEdit')"
|
||||
v-if="IsDicom" />
|
||||
<!--检查模态-->
|
||||
<el-table-column
|
||||
prop="Modalities"
|
||||
:label="$t('trials:uploadImage:table:Modalities')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<el-table-column prop="Modalities" :label="$t('trials:uploadImage:table:Modalities')" v-if="IsDicom" />
|
||||
<!--检查部位-->
|
||||
<el-table-column
|
||||
prop="BodyPartForEdit"
|
||||
:label="$t('trials:uploadImage:table:BodyPartForEdit')"
|
||||
v-if="IsDicom"
|
||||
>
|
||||
<el-table-column prop="BodyPartForEdit" :label="$t('trials:uploadImage:table:BodyPartForEdit')"
|
||||
v-if="IsDicom">
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
$fd(
|
||||
'Bodypart',
|
||||
scope.row.BodyPartForEdit,
|
||||
'Code',
|
||||
{ Bodypart: bodyPart },
|
||||
'Name'
|
||||
)
|
||||
}}</span>
|
||||
<span>{{ getBodyPart(scope.row.BodyPartForEdit, scope.row.BodyPartForEditOther) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--序列数量-->
|
||||
<el-table-column
|
||||
prop="ReadingSeriesCount"
|
||||
:label="$t('trials:uploadImage:table:SeriesCount')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<el-table-column prop="ReadingSeriesCount" :label="$t('trials:uploadImage:table:SeriesCount')"
|
||||
v-if="IsDicom" />
|
||||
<!--图像数量-->
|
||||
<el-table-column
|
||||
prop="ReadingInstanceCount"
|
||||
:label="$t('trials:uploadImage:table:InstanceCount')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<el-table-column prop="ReadingInstanceCount" :label="$t('trials:uploadImage:table:InstanceCount')"
|
||||
v-if="IsDicom" />
|
||||
<!--检查时间-->
|
||||
<el-table-column
|
||||
prop="StudyTime"
|
||||
:label="$t('trials:uploadImage:table:StudyTime')"
|
||||
v-if="IsDicom"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column prop="StudyTime" :label="$t('trials:uploadImage:table:StudyTime')" v-if="IsDicom"
|
||||
min-width="130" />
|
||||
<!--检查模态-->
|
||||
<el-table-column
|
||||
prop="Modality"
|
||||
:label="$t('trials:uploadImage:table:Modalities')"
|
||||
v-if="!IsDicom"
|
||||
/>
|
||||
<el-table-column prop="Modality" :label="$t('trials:uploadImage:table:Modalities')" v-if="!IsDicom" />
|
||||
<!--检查部位-->
|
||||
<el-table-column
|
||||
prop="BodyPart"
|
||||
:label="$t('trials:uploadImage:table:BodyPartForEdit')"
|
||||
v-if="!IsDicom"
|
||||
>
|
||||
<el-table-column prop="BodyPart" :label="$t('trials:uploadImage:table:BodyPartForEdit')" v-if="!IsDicom">
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
$fd(
|
||||
'Bodypart',
|
||||
scope.row.BodyPart,
|
||||
'Code',
|
||||
{ Bodypart: bodyPart },
|
||||
'Name'
|
||||
)
|
||||
}}</span>
|
||||
<span>{{ getBodyPart(scope.row.BodyPart, scope.row.BodyPartForEditOther) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--文件数量-->
|
||||
<el-table-column
|
||||
prop="ReadingFileCount"
|
||||
:label="$t('trials:uploadImage:table:FileCount')"
|
||||
v-if="!IsDicom"
|
||||
/>
|
||||
<el-table-column prop="ReadingFileCount" :label="$t('trials:uploadImage:table:FileCount')" v-if="!IsDicom" />
|
||||
<!--检查时间-->
|
||||
<el-table-column
|
||||
prop="ImageDate"
|
||||
:label="$t('trials:uploadImage:table:StudyTime')"
|
||||
v-if="!IsDicom"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
width="80"
|
||||
>
|
||||
<el-table-column prop="ImageDate" :label="$t('trials:uploadImage:table:StudyTime')" v-if="!IsDicom"
|
||||
min-width="130" />
|
||||
<el-table-column :label="$t('common:action:action')" fixed="right" width="80" v-if="isUpload">
|
||||
<template slot-scope="scope">
|
||||
<!--预览--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-view"
|
||||
:title="$t('trials:uploadImage:button:preview')"
|
||||
v-if="!isUpload"
|
||||
@click.stop="preview(scope.row)"
|
||||
/>
|
||||
<!-- <el-button circle icon="el-icon-view" :title="$t('trials:uploadImage:button:preview')" v-if="!isUpload"
|
||||
@click.stop="preview(scope.row)" /> -->
|
||||
<!--编辑--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-edit-outline"
|
||||
:title="$t('trials:uploadImage:button:edit')"
|
||||
v-else
|
||||
@click.stop="openEdit(scope.row)"
|
||||
/>
|
||||
<el-button circle icon="el-icon-edit-outline" :title="$t('trials:uploadImage:button:edit')"
|
||||
@click.stop="openEdit(scope.row)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -124,42 +58,20 @@
|
||||
<!--新增检查部位-->
|
||||
<base-model v-if="editModality_model.visible" :config="editModality_model">
|
||||
<template slot="dialog-body">
|
||||
<el-form
|
||||
ref="editModalityform"
|
||||
:inline="true"
|
||||
:model="form"
|
||||
class="demo-form-inline"
|
||||
:rules="rules"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('trials:uploadImage:form:ModalityForEdit')"
|
||||
prop="Modality"
|
||||
label-width="150px"
|
||||
>
|
||||
<el-form ref="editModalityform" :inline="true" :model="form" class="demo-form-inline" :rules="rules">
|
||||
<el-form-item :label="$t('trials:uploadImage:form:ModalityForEdit')" prop="Modality" label-width="150px">
|
||||
<el-select v-model="form.Modality" placeholder="">
|
||||
<el-option
|
||||
v-for="item in TrialModality"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
<el-option v-for="item in TrialModality" :key="item" :label="item" :value="item">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="updateTaskStudyModality"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-button type="primary" @click="updateTaskStudyModality" :loading="loading">
|
||||
{{ $t('common:button:confirm') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="editModality_model.visible = false"
|
||||
:loading="loading"
|
||||
>
|
||||
<el-button @click="editModality_model.visible = false" :loading="loading">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -180,9 +92,9 @@ export default {
|
||||
},
|
||||
},
|
||||
bodyPart: {
|
||||
type: Array,
|
||||
type: Object,
|
||||
default: () => {
|
||||
return []
|
||||
return {}
|
||||
},
|
||||
},
|
||||
modelList: {
|
||||
@@ -200,16 +112,33 @@ export default {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
},
|
||||
subjectVisitId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
IsDicom: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isUpload: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
IsImageSegment: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
isDownload: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
Criterion: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'base-model': baseModel,
|
||||
@@ -236,6 +165,7 @@ export default {
|
||||
],
|
||||
},
|
||||
loading: false,
|
||||
BodyPart: {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -244,15 +174,23 @@ export default {
|
||||
let routeData = null
|
||||
if (this.IsDicom) {
|
||||
var token = getToken()
|
||||
let trialId = this.$route.query.trialId
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showdicom?studyId=${row.Id}&TokenKey=${token}&type=Study&visitTaskId=${this.visitTaskId}`,
|
||||
path: `/showvisitdicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&isReading=1&TokenKey=${token}`,
|
||||
})
|
||||
} else {
|
||||
let trialId = this.$route.query.trialId
|
||||
var token = getToken()
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&TokenKey=${token}`,
|
||||
})
|
||||
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true`,
|
||||
})
|
||||
} else {
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true`,
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
@@ -284,8 +222,28 @@ export default {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
getBodyPart(bodyPart, other) {
|
||||
if (!bodyPart && !other) return ''
|
||||
var separator = ','
|
||||
if (bodyPart.indexOf('|') > -1) {
|
||||
separator = '|'
|
||||
} else if (bodyPart.indexOf(',') > -1) {
|
||||
separator = ','
|
||||
} else if (bodyPart.indexOf(',') > -1) {
|
||||
separator = ','
|
||||
}
|
||||
var arr = bodyPart.split(separator)
|
||||
console.log(this.bodyPart)
|
||||
var newArr = arr.map((i) => {
|
||||
return this.$fd('Bodypart', i.trim(), 'Code', this.bodyPart, 'Name')
|
||||
})
|
||||
if (other) {
|
||||
newArr.push(other)
|
||||
}
|
||||
newArr = newArr.filter(Boolean)
|
||||
return newArr.join(' | ')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
@@ -29,6 +29,10 @@ export default {
|
||||
MedicalAudit: 215, // 医学审核
|
||||
HeavyReadingApproval: 216, // 重阅审批
|
||||
ResetAndAsyncCriterion: 218, //同步签名
|
||||
ResetImageQualityControlQuestion: 112, // 重置影像质控问题
|
||||
CreateReviewTask: 113, // 生成复核任务
|
||||
ReviewImageQualityControlQuestion: 219, // 复核质控问题
|
||||
CorrectImageExaminationInformation: 220, // 更正影像检查信息
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1763446648844" class="icon" viewBox="0 0 1321 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3570" xmlns:xlink="http://www.w3.org/1999/xlink" width="258.0078125" height="200"><path d="M1187.981 845.871H200.885V120.065C200.885 91.032 177.659 62 142.82 62s-58.064 23.226-58.064 58.065v783.87c0 29.033 23.225 58.065 58.064 58.065h1045.161c29.033 0 58.065-23.226 58.065-58.065s-29.032-58.064-58.065-58.064z" fill="#1296db" p-id="3571"></path><path d="M287.981 317.484L555.078 485.87c11.613 5.806 17.42 5.806 29.032 5.806 17.42 0 34.84-5.806 46.452-23.225l185.806-255.484 191.613 145.161c23.226 17.42 58.065 11.613 75.484-11.613 17.42-23.226 11.613-58.064-11.613-75.484L839.594 96.84c-23.226-17.42-58.064-11.613-75.484 11.613L572.497 363.935 346.046 224.581c-23.226-17.42-58.065-5.807-75.484 17.419s-5.806 58.065 17.42 75.484z m29.033 505.161c29.032 0 58.064-23.226 58.064-58.064V532.323c0-29.033-23.226-58.065-58.064-58.065s-58.065 23.226-58.065 58.065v238.064c5.807 29.032 29.032 52.258 58.065 52.258zM502.82 619.42v150.968c0 29.032 23.226 58.065 58.065 58.065s58.064-23.226 58.064-58.065V619.42c0-29.032-23.226-58.064-58.064-58.064s-58.065 29.032-58.065 58.064z" fill="#1296db" p-id="3572"></path><path d="M740.885 416.194v354.193c0 29.032 23.225 58.065 58.064 58.065s58.065-23.226 58.065-58.065V416.194c0-29.033-23.226-58.065-58.065-58.065s-58.064 29.032-58.064 58.065z m296.129 92.903c-29.033 0-58.065 23.226-58.065 58.064v203.226c0 29.032 23.226 58.065 58.065 58.065s58.064-23.226 58.064-58.065V567.161c0-29.032-29.032-58.064-58.064-58.064z" fill="#1296db" p-id="3573"></path></svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
+16
-1
@@ -202,6 +202,7 @@ async function VueInit() {
|
||||
// 获取版本信息
|
||||
let PublishInfo = await getCurrentPublishInfo();
|
||||
Vue.prototype.$version = PublishInfo.Result;
|
||||
Vue.prototype.$companyInfo = PublishInfo.OtherInfo;
|
||||
// 获取检查部位
|
||||
Vue.prototype.$getBodyPart = (id) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
@@ -275,6 +276,20 @@ async function VueInit() {
|
||||
}
|
||||
return companyName;
|
||||
}
|
||||
Vue.prototype.$reg = () => {
|
||||
if (localStorage.getItem('CompanyInfo')) {
|
||||
let { EmailRegexStr } = JSON.parse(localStorage.getItem('CompanyInfo'))
|
||||
if (EmailRegexStr) {
|
||||
return { EmailRegexStr }
|
||||
}
|
||||
} else if (Vue.prototype.$companyInfo) {
|
||||
let { EmailRegexStr } = Vue.prototype.$companyInfo
|
||||
if (EmailRegexStr) {
|
||||
return { EmailRegexStr }
|
||||
}
|
||||
}
|
||||
return { EmailRegexStr: '^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$' };
|
||||
}
|
||||
Vue.prototype.$updateDictionary = function () {
|
||||
Vue.prototype.$d = function (code) {
|
||||
var dictInfo = res.Result
|
||||
@@ -316,7 +331,7 @@ async function VueInit() {
|
||||
})
|
||||
}
|
||||
let CompanyInfo = JSON.parse(localStorage.getItem('CompanyInfo'))
|
||||
if (CompanyInfo && CompanyInfo.SystemShortName) {
|
||||
if (CompanyInfo && CompanyInfo.SystemShortName && text.toUpperCase() !== "CIRCLE") {
|
||||
let test = new RegExp('IRC', 'ig')
|
||||
text = text.replace(test, CompanyInfo.SystemShortName)
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ const getters = {
|
||||
paymentHistoryQuery: state => state.financials.paymentHistoryQuery,
|
||||
revenusQuery: state => state.financials.revenusQuery,
|
||||
visitTaskList: state => state.reading.visitTaskList,
|
||||
BodyPart: state => state.reading.BodyPart,
|
||||
organList: state => state.reading.organList,
|
||||
seriesStack: state => state.reading.seriesStack,
|
||||
activeHangingAgreement: state => state.reading.activeHangingAgreement,
|
||||
|
||||
@@ -12,6 +12,7 @@ import { getCustomTag } from '@/api/reading'
|
||||
|
||||
import requestPoolManager from '@/utils/request-pool'
|
||||
import { getReadingVisitStudyList } from '@/api/trials'
|
||||
import { getNetWorkSpeed, setNetWorkSpeedSizeAll, workSpeedclose } from "@/utils"
|
||||
const hangingAgreement = [
|
||||
{ name: 'A', row: 1, col: 1 },
|
||||
{ name: 'A|A', row: 1, col: 2 },
|
||||
@@ -31,13 +32,21 @@ const getDefaultState = () => {
|
||||
lastCanvasTaskId: '',
|
||||
imageQuality: null,
|
||||
imageQualityIssues: null,
|
||||
currentLoadIns: []
|
||||
currentLoadIns: [],
|
||||
BodyPart: []
|
||||
}
|
||||
}
|
||||
function getQuestions(questions) {
|
||||
const criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
questions.forEach(item => {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
item.TableQuestions.Questions.forEach(question => {
|
||||
if (question.Type === 'select' && question.OptionTypeEnum === 1) {
|
||||
item.TableQuestions.Answers.forEach((answer) => {
|
||||
answer[question.Id] = answer[question.Id] ? JSON.parse(answer[question.Id]) : []
|
||||
})
|
||||
}
|
||||
})
|
||||
item.TableQuestions.Answers.forEach(answerObj => {
|
||||
answerObj.isDicomReading = answerObj.IsDicomReading === 'True'
|
||||
|
||||
@@ -170,6 +179,45 @@ function getQuestionAnswer(questions, questionMark, answers) {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
function getQuerys(e) {
|
||||
if (!e) return "";
|
||||
var t = {},
|
||||
r = [],
|
||||
n = "",
|
||||
a = "";
|
||||
try {
|
||||
var i = [];
|
||||
if (e.indexOf("?") >= 0 && (i = e.substring(e.indexOf("?") + 1, e.length).split("&")), i.length > 0) for (var o in i) n = (r = i[o].split("="))[0],
|
||||
a = r[1],
|
||||
t[n] = a
|
||||
} catch (s) {
|
||||
t = {}
|
||||
}
|
||||
return t
|
||||
}
|
||||
async function getBodyPart(bodyPart, other) {
|
||||
if (!bodyPart && !other) return ''
|
||||
var separator = ','
|
||||
if (bodyPart.indexOf('|') > -1) {
|
||||
separator = '|'
|
||||
} else if (bodyPart.indexOf(',') > -1) {
|
||||
separator = ','
|
||||
} else if (bodyPart.indexOf(',') > -1) {
|
||||
separator = ','
|
||||
}
|
||||
let BodyPart = {}
|
||||
let query = getQuerys(window.location.href)
|
||||
BodyPart.Bodypart = await Vue.prototype.$getBodyPart(query.trialId)
|
||||
var arr = bodyPart.split(separator)
|
||||
var newArr = arr.map((i) => {
|
||||
return Vue.prototype.$fd('Bodypart', i.trim(), 'Code', BodyPart, 'Name')
|
||||
})
|
||||
if (other) {
|
||||
newArr.push(other)
|
||||
}
|
||||
newArr = newArr.filter(Boolean)
|
||||
return newArr
|
||||
}
|
||||
// function getKeySeriesInfo(keyInstance, series) {
|
||||
// const obj = {}
|
||||
// const set = new Set()
|
||||
@@ -644,15 +692,15 @@ const actions = {
|
||||
resolve(noneDicomMeasureData)
|
||||
})
|
||||
},
|
||||
addMeasuredData({ state }, obj) {
|
||||
addMeasuredData({ state }, obj) {
|
||||
return new Promise(resolve => {
|
||||
const criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
|
||||
var measureData = state.visitTaskList[index].MeasureData
|
||||
// var idx = measureData.findIndex(item => item.MeasureData.uuid === obj.data.MeasureData.data.uuid)
|
||||
|
||||
|
||||
if (criterionType === 21) {
|
||||
let i = measureData.findIndex(i=>i.TableQuestionId === obj.data.TableQuestionId)
|
||||
let i = measureData.findIndex(i => i.TableQuestionId === obj.data.TableQuestionId)
|
||||
if (i > -1) {
|
||||
for (const k in state.visitTaskList[index].MeasureData[i]) {
|
||||
if (k !== 'Id' && obj.data[k]) {
|
||||
@@ -676,7 +724,7 @@ const actions = {
|
||||
console.log('新增标记成功')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
|
||||
resolve()
|
||||
})
|
||||
@@ -775,15 +823,15 @@ const actions = {
|
||||
const criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
if (criterionType === 21) {
|
||||
const i = measureData.findIndex(item => item.QuestionId === obj.questionId && item.OrderMarkName === obj.orderMarkName)
|
||||
if (i > -1) {
|
||||
if (measureData[i].FristAddTaskId) {
|
||||
measureData[i].MeasureData = ''
|
||||
console.log('清除标记成功', i)
|
||||
} else {
|
||||
measureData.splice(i, 1)
|
||||
console.log('移除标记成功', i)
|
||||
}
|
||||
if (i > -1) {
|
||||
if (measureData[i].FristAddTaskId) {
|
||||
measureData[i].MeasureData = ''
|
||||
console.log('清除标记成功', i)
|
||||
} else {
|
||||
measureData.splice(i, 1)
|
||||
console.log('移除标记成功', i)
|
||||
}
|
||||
}
|
||||
state.visitTaskList[index].MeasureData = measureData
|
||||
} else {
|
||||
var idx = measureData.findIndex(item => item.QuestionId === obj.questionId && item.RowIndex === obj.rowIndex)
|
||||
@@ -810,7 +858,7 @@ const actions = {
|
||||
state.visitTaskList[index].MeasureData = measureData
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// if (idx > -1) {
|
||||
// measureData.splice(idx, 1)
|
||||
|
||||
@@ -849,6 +897,20 @@ const actions = {
|
||||
var studyList = []
|
||||
var keyImages = []
|
||||
getReadingVisitStudyList(obj.trialId, obj.subjectVisitId, obj.visitTaskId).then(res => {
|
||||
try {
|
||||
state.BodyPart = []
|
||||
res.Result.forEach(async item => {
|
||||
let arr = await getBodyPart(item.BodyPartForEdit, item.BodyPartForEditOther)
|
||||
state.BodyPart.push({
|
||||
StudyId: item.StudyId,
|
||||
StudyCode: item.StudyCode,
|
||||
BodyPart: arr,
|
||||
Modalities: item.Modalities
|
||||
})
|
||||
})
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
const i = res.Result.findIndex(i => i.IsCriticalSequence)
|
||||
if (i > -1) {
|
||||
const seriesList = res.Result[i].SeriesList && res.Result[i].SeriesList
|
||||
@@ -1072,16 +1134,22 @@ const actions = {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let file = series.instanceInfoList.find(item => item.ImageId === obj.imageId)
|
||||
if (file) {
|
||||
getNetWorkSpeed()
|
||||
setNetWorkSpeedSizeAll(obj.percentComplete, obj.FileTotal, obj.imageId)
|
||||
}
|
||||
if (prefetchInstanceCount >= instanceCount * 100) {
|
||||
series.prefetchInstanceCount = instanceCount * 100
|
||||
// 设置当前序列状态为已下载完成
|
||||
series.loadStatus = true
|
||||
workSpeedclose()
|
||||
}
|
||||
if (prefetchInstanceCount2 !== null && instanceCount2 !== null && prefetchInstanceCount2 >= instanceCount2 * 100) {
|
||||
pSeries.prefetchInstanceCount = instanceCount2 * 100
|
||||
// 设置当前序列状态为已下载完成
|
||||
pSeries.loadStatus = true
|
||||
workSpeedclose()
|
||||
}
|
||||
} catch (e) {
|
||||
console.log('error')
|
||||
|
||||
@@ -10,6 +10,8 @@ const getDefaultState = () => {
|
||||
unlock: false,
|
||||
config: {},
|
||||
uploadTip: '0.00KB/s',
|
||||
downloadTip: '0.00KB/s',
|
||||
downloadSize: '',
|
||||
timer: null,
|
||||
whiteList: [],
|
||||
checkTaskId: null
|
||||
|
||||
@@ -357,4 +357,18 @@ body .el-table th.gutter {
|
||||
|
||||
.el-message-box__wrapper {
|
||||
z-index: 9999 !important;
|
||||
}
|
||||
|
||||
.svg-readingChart {
|
||||
width: 28px !important;
|
||||
height: 30px !important;
|
||||
margin-left: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.svg-readingChart-mini {
|
||||
width: 18px !important;
|
||||
height: 20px !important;
|
||||
vertical-align: -0.4em !important;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -0,0 +1,346 @@
|
||||
class FileNameSorter {
|
||||
/**
|
||||
* 判断是否为纯数字字符串
|
||||
* @param {any} value - 要检查的值
|
||||
* @returns {boolean} 是否为纯数字
|
||||
*/
|
||||
static isPureNumber(value) {
|
||||
if (typeof value !== 'string') return false;
|
||||
return /^\d+$/.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取排序键值
|
||||
* @param {any} item - 要排序的项目
|
||||
* @returns {Array} 排序键值数组
|
||||
*/
|
||||
static getSortKey(item) {
|
||||
const str = String(item);
|
||||
const isNumber = this.isPureNumber(str);
|
||||
|
||||
// 排序优先级: [类型优先级, 数字值/字符串值]
|
||||
if (isNumber) {
|
||||
// 纯数字: 类型优先级为0, 使用数字值排序
|
||||
return [0, BigInt(str)];
|
||||
} else {
|
||||
// 非纯数字: 类型优先级为1, 使用字符串排序
|
||||
return [1, str.toLowerCase()];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件名排序
|
||||
* @param {Array} arr - 要排序的数组
|
||||
* @param {Object} options - 排序选项
|
||||
* @returns {Array} 排序后的数组
|
||||
*/
|
||||
static sortFileNames(arr, options = {}) {
|
||||
if (!Array.isArray(arr)) {
|
||||
throw new TypeError('输入必须是一个数组');
|
||||
}
|
||||
|
||||
const {
|
||||
direction = 'asc', // 'asc' 升序, 'desc' 降序
|
||||
caseSensitive = false, // 是否区分大小写
|
||||
trim = true, // 是否去除前后空格
|
||||
key = null
|
||||
} = options;
|
||||
|
||||
// 创建数组的副本
|
||||
const result = [...arr];
|
||||
|
||||
return result.sort((a, b) => {
|
||||
let aStr = key ? String(a[key]).split(".")[0] : String(a);
|
||||
let bStr = key ? String(b[key]).split(".")[0] : String(b);
|
||||
// 处理空格
|
||||
if (trim) {
|
||||
aStr = aStr.trim();
|
||||
bStr = bStr.trim();
|
||||
}
|
||||
|
||||
// 处理大小写
|
||||
if (!caseSensitive) {
|
||||
aStr = aStr.toLowerCase();
|
||||
bStr = bStr.toLowerCase();
|
||||
}
|
||||
|
||||
// 获取排序键值
|
||||
const aKey = this.getSortKey(aStr);
|
||||
const bKey = this.getSortKey(bStr);
|
||||
|
||||
// 比较类型优先级
|
||||
if (aKey[0] !== bKey[0]) {
|
||||
// 纯数字(0) < 非纯数字(1)
|
||||
return direction === 'asc' ? aKey[0] - bKey[0] : bKey[0] - aKey[0];
|
||||
}
|
||||
|
||||
// 相同类型下的比较
|
||||
if (aKey[0] === 0) {
|
||||
// 都是纯数字,按数字大小比较
|
||||
if (aKey[1] < bKey[1]) return direction === 'asc' ? -1 : 1;
|
||||
if (aKey[1] > bKey[1]) return direction === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
} else {
|
||||
// 都是非纯数字,按字符串比较
|
||||
if (aStr < bStr) return direction === 'asc' ? -1 : 1;
|
||||
if (aStr > bStr) return direction === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 自然排序 - 处理文件名中的数字序列
|
||||
* 例如: file1, file2, file10
|
||||
* @param {Array} arr - 要排序的数组
|
||||
* @param {Object} options - 排序选项
|
||||
* @returns {Array} 排序后的数组
|
||||
*/
|
||||
static naturalSort(arr, options = {}) {
|
||||
const {
|
||||
direction = 'asc',
|
||||
caseSensitive = false
|
||||
} = options;
|
||||
|
||||
return [...arr].sort((a, b) => {
|
||||
const aStr = String(a);
|
||||
const bStr = String(b);
|
||||
|
||||
// 检查是否都是纯数字
|
||||
const aIsPureNumber = this.isPureNumber(aStr);
|
||||
const bIsPureNumber = this.isPureNumber(bStr);
|
||||
|
||||
// 如果一个纯数字,一个非纯数字
|
||||
if (aIsPureNumber && !bIsPureNumber) {
|
||||
return direction === 'asc' ? -1 : 1;
|
||||
}
|
||||
if (!aIsPureNumber && bIsPureNumber) {
|
||||
return direction === 'asc' ? 1 : -1;
|
||||
}
|
||||
|
||||
// 都是纯数字,按数字比较
|
||||
if (aIsPureNumber && bIsPureNumber) {
|
||||
const aNum = BigInt(aStr);
|
||||
const bNum = BigInt(bStr);
|
||||
|
||||
if (aNum < bNum) return direction === 'asc' ? -1 : 1;
|
||||
if (aNum > bNum) return direction === 'asc' ? 1 : -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// 都是非纯数字,使用自然排序算法
|
||||
return this.naturalCompare(aStr, bStr, direction, caseSensitive);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 自然比较算法
|
||||
* @private
|
||||
*/
|
||||
static naturalCompare(a, b, direction = 'asc', caseSensitive = false) {
|
||||
let aStr = caseSensitive ? a : a.toLowerCase();
|
||||
let bStr = caseSensitive ? b : b.toLowerCase();
|
||||
|
||||
const regex = /(\d+|\D+)/g;
|
||||
const aParts = aStr.match(regex) || [];
|
||||
const bParts = bStr.match(regex) || [];
|
||||
|
||||
const maxLength = Math.max(aParts.length, bParts.length);
|
||||
|
||||
for (let i = 0; i < maxLength; i++) {
|
||||
const aPart = aParts[i] || '';
|
||||
const bPart = bParts[i] || '';
|
||||
|
||||
const aIsNumber = /^\d+$/.test(aPart);
|
||||
const bIsNumber = /^\d+$/.test(bPart);
|
||||
|
||||
// 如果都是数字,按数字比较
|
||||
if (aIsNumber && bIsNumber) {
|
||||
const aNum = BigInt(aPart);
|
||||
const bNum = BigInt(bPart);
|
||||
|
||||
if (aNum < bNum) return direction === 'asc' ? -1 : 1;
|
||||
if (aNum > bNum) return direction === 'asc' ? 1 : -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
// 都是文本,按字符串比较
|
||||
if (aPart < bPart) return direction === 'asc' ? -1 : 1;
|
||||
if (aPart > bPart) return direction === 'asc' ? 1 : -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分组排序 - 将纯数字和非纯数字分开显示
|
||||
* @param {Array} arr - 要排序的数组
|
||||
* @param {Object} options - 排序选项
|
||||
* @returns {Array} 排序后的数组
|
||||
*/
|
||||
static groupSort(arr, options = {}) {
|
||||
const {
|
||||
direction = 'asc',
|
||||
groupOrder = 'numbers-first' // 'numbers-first' 或 'names-first'
|
||||
} = options;
|
||||
|
||||
// 分组
|
||||
const numbers = [];
|
||||
const names = [];
|
||||
|
||||
arr.forEach(item => {
|
||||
const str = String(item);
|
||||
if (this.isPureNumber(str)) {
|
||||
numbers.push(item);
|
||||
} else {
|
||||
names.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// 对各组排序
|
||||
const sortedNumbers = this.sortFileNames(numbers, { direction });
|
||||
const sortedNames = this.sortFileNames(names, { direction });
|
||||
|
||||
// 按指定顺序合并
|
||||
if (groupOrder === 'numbers-first') {
|
||||
return [...sortedNumbers, ...sortedNames];
|
||||
} else {
|
||||
return [...sortedNames, ...sortedNumbers];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 文件扩展名排序 - 先按扩展名排序,再按文件名排序
|
||||
* @param {Array} arr - 要排序的数组
|
||||
* @param {Object} options - 排序选项
|
||||
* @returns {Array} 排序后的数组
|
||||
*/
|
||||
static sortByExtension(arr, options = {}) {
|
||||
const {
|
||||
direction = 'asc',
|
||||
extensionsFirst = false // 扩展名优先还是文件名优先
|
||||
} = options;
|
||||
|
||||
return [...arr].sort((a, b) => {
|
||||
const aStr = String(a);
|
||||
const bStr = String(b);
|
||||
|
||||
// 分离文件名和扩展名
|
||||
const getFileParts = (str) => {
|
||||
const lastDotIndex = str.lastIndexOf('.');
|
||||
if (lastDotIndex > 0) {
|
||||
return {
|
||||
name: str.substring(0, lastDotIndex),
|
||||
ext: str.substring(lastDotIndex + 1)
|
||||
};
|
||||
}
|
||||
return { name: str, ext: '' };
|
||||
};
|
||||
|
||||
const aParts = getFileParts(aStr);
|
||||
const bParts = getFileParts(bStr);
|
||||
|
||||
let compareResult;
|
||||
|
||||
if (extensionsFirst) {
|
||||
// 先比较扩展名
|
||||
compareResult = this.sortFileNames([aParts.ext, bParts.ext], { direction })[0] === aParts.ext ? -1 : 1;
|
||||
if (compareResult !== 0) return compareResult;
|
||||
|
||||
// 扩展名相同,再比较文件名
|
||||
return this.sortFileNames([aParts.name, bParts.name], { direction })[0] === aParts.name ? -1 : 1;
|
||||
} else {
|
||||
// 先比较文件名
|
||||
compareResult = this.sortFileNames([aParts.name, bParts.name], { direction })[0] === aParts.name ? -1 : 1;
|
||||
if (compareResult !== 0) return compareResult;
|
||||
|
||||
// 文件名相同,再比较扩展名
|
||||
return this.sortFileNames([aParts.ext, bParts.ext], { direction })[0] === aParts.ext ? -1 : 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 测试和演示函数
|
||||
*/
|
||||
static demonstrate() {
|
||||
const testData = [
|
||||
'100',
|
||||
'23',
|
||||
'1',
|
||||
'003',
|
||||
'file.txt',
|
||||
'10',
|
||||
'5',
|
||||
'alpha',
|
||||
'beta',
|
||||
'gamma',
|
||||
'00100',
|
||||
'zebra',
|
||||
'apple',
|
||||
'banana',
|
||||
'123',
|
||||
'file10.txt',
|
||||
'file2.txt',
|
||||
'File1.txt',
|
||||
'file20.txt',
|
||||
'image.jpg',
|
||||
'document.pdf',
|
||||
'data.xlsx'
|
||||
];
|
||||
|
||||
console.log('=== 文件名排序演示 ===\n');
|
||||
|
||||
console.log('原始数据:');
|
||||
console.log(testData);
|
||||
|
||||
console.log('\n1. 基本排序 (纯数字 < 非纯数字):');
|
||||
const basicSorted = this.sortFileNames(testData);
|
||||
console.log(basicSorted);
|
||||
|
||||
console.log('\n2. 自然排序 (智能数字识别):');
|
||||
const naturalSorted = this.naturalSort(testData);
|
||||
console.log(naturalSorted);
|
||||
|
||||
console.log('\n3. 分组排序 (数字组和文件组):');
|
||||
const groupSorted = this.groupSort(testData);
|
||||
console.log(groupSorted);
|
||||
|
||||
console.log('\n4. 降序排序:');
|
||||
const descSorted = this.sortFileNames(testData, { direction: 'desc' });
|
||||
console.log(descSorted);
|
||||
|
||||
console.log('\n5. 按扩展名排序:');
|
||||
const extSorted = this.sortByExtension(testData);
|
||||
console.log(extSorted);
|
||||
|
||||
console.log('\n6. 大小写敏感排序:');
|
||||
const caseSensitiveSorted = this.sortFileNames(testData, { caseSensitive: true });
|
||||
console.log(caseSensitiveSorted);
|
||||
|
||||
// 验证排序规则
|
||||
console.log('\n=== 排序规则验证 ===');
|
||||
const validationData = ['100', '23', 'file.txt', '1', 'alpha', '003', '10'];
|
||||
console.log('验证数据:', validationData);
|
||||
console.log('排序结果:', this.sortFileNames(validationData));
|
||||
console.log('规则验证:');
|
||||
console.log(' - 纯数字: 1, 3(003), 10, 23, 100 (按数字大小)');
|
||||
console.log(' - 非纯数字: alpha, file.txt (按字母顺序)');
|
||||
console.log(' - 非纯数字 > 纯数字');
|
||||
|
||||
return {
|
||||
basic: basicSorted,
|
||||
natural: naturalSorted,
|
||||
group: groupSorted,
|
||||
descending: descSorted,
|
||||
byExtension: extSorted,
|
||||
caseSensitive: caseSensitiveSorted
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = FileNameSorter;
|
||||
} else if (typeof window !== 'undefined') {
|
||||
window.FileNameSorter = FileNameSorter;
|
||||
}
|
||||
@@ -15,6 +15,7 @@ export const anonymization = function (file, config) {
|
||||
let dataset = dcmjs.data.DicomMessage.readFile(buffer)
|
||||
for (var i = 0; i < AnonymizeFixedList.length; i++) {
|
||||
let AnonymizeFixed = AnonymizeFixedList[i]
|
||||
if (!dataset.dict.hasOwnProperty(`${AnonymizeFixed.Group + AnonymizeFixed.Element}`)) continue
|
||||
if (dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element]) {
|
||||
dataset.dict[AnonymizeFixed.Group + AnonymizeFixed.Element].Value[0] = AnonymizeFixed.ReplaceValue
|
||||
} else {
|
||||
@@ -28,6 +29,7 @@ export const anonymization = function (file, config) {
|
||||
}
|
||||
for (var i = 0; i < AnonymizeNotFixedList.length; i++) {
|
||||
let AnonymizeNotFixed = AnonymizeNotFixedList[i]
|
||||
// if (!dataset.dict.hasOwnProperty(`${AnonymizeNotFixed.Group + AnonymizeNotFixed.Element}`)) continue
|
||||
if (AnonymizeNotFixed.Group + AnonymizeNotFixed.Element === '00100020') {
|
||||
console.log(`${DicomStoreInfo.TrialCode}_${DicomStoreInfo.SubjectCode}`)
|
||||
if (dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element]) {
|
||||
@@ -42,7 +44,7 @@ export const anonymization = function (file, config) {
|
||||
}
|
||||
} else {
|
||||
if (dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element]) {
|
||||
dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element].Value[0] = DicomStoreInfo[AnonymizeNotFixed.ReplaceValue] ? DicomStoreInfo[AnonymizeNotFixed.ReplaceValue].toString() : ''
|
||||
dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element].Value[0] = DicomStoreInfo[AnonymizeNotFixed.ReplaceValue] || Number(DicomStoreInfo[AnonymizeNotFixed.ReplaceValue]) === 0 ? DicomStoreInfo[AnonymizeNotFixed.ReplaceValue].toString() : ''
|
||||
} else {
|
||||
dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element] = {
|
||||
vr: AnonymizeNotFixed.ValueRepresentation,
|
||||
@@ -53,9 +55,9 @@ export const anonymization = function (file, config) {
|
||||
}
|
||||
}
|
||||
}
|
||||
// console.log(dataset)
|
||||
|
||||
try {
|
||||
let newDicomFile = dataset.write()
|
||||
let newDicomFile = dataset.write() // fragmentMultiframe 原始数据是否进行分割
|
||||
const bufferArray = new Uint8Array(newDicomFile)
|
||||
const blob = new Blob([bufferArray], { type: 'application/octet-stream' })
|
||||
resolve({ blob, pixelDataElement })
|
||||
|
||||
@@ -8508,6 +8508,8 @@
|
||||
var binaryStream;
|
||||
var _writeOptions$fragmen = writeOptions.fragmentMultiframe,
|
||||
fragmentMultiframe = _writeOptions$fragmen === void 0 ? true : _writeOptions$fragmen;
|
||||
var _writeOptions$offset = writeOptions.startOffset,
|
||||
isNeedStartOffset = _writeOptions$offset === void 0 ? true : _writeOptions$offset;
|
||||
value = value === null || value === undefined ? [] : value;
|
||||
|
||||
if (isEncapsulated) {
|
||||
@@ -8535,7 +8537,9 @@
|
||||
for (i = 0; i < frames; i++) {
|
||||
var _needsPadding = Boolean(value[i].byteLength & 1);
|
||||
|
||||
startOffset.push(binaryStream.size);
|
||||
if (isNeedStartOffset) {
|
||||
startOffset.push(binaryStream.size);
|
||||
}
|
||||
var frameBuffer = value[i],
|
||||
frameStream = new ReadBufferStream(frameBuffer);
|
||||
var fragmentsLength = 1;
|
||||
|
||||
+96
-1
@@ -1,4 +1,5 @@
|
||||
|
||||
import store from "@/store";
|
||||
/**
|
||||
* Parse the time to string
|
||||
* @param {(Object|string|number)} time
|
||||
@@ -92,7 +93,6 @@ export function deepClone(source, map = new WeakMap()) {
|
||||
|
||||
return target;
|
||||
}
|
||||
|
||||
export function formatSize(size, fixed = 2) {
|
||||
if (isNaN(parseFloat(size))) return ''
|
||||
let kbSize = size / 1024
|
||||
@@ -101,4 +101,99 @@ export function formatSize(size, fixed = 2) {
|
||||
}
|
||||
let mbSize = kbSize / 1024
|
||||
return `${mbSize.toFixed(fixed)}MB`
|
||||
}
|
||||
|
||||
let timer = null, // 网速定时器
|
||||
lastPercentage = 0,
|
||||
percentageById = {},
|
||||
imageId = null,
|
||||
bytesReceivedPerSecond = {}; // 时间节点上传文件总量
|
||||
// 获取网速
|
||||
export function getNetWorkSpeed() {
|
||||
if (timer) return false;
|
||||
// if (lastPercentage < 100) return false;
|
||||
if (imageId && imageId !== Id) return false
|
||||
imageId = null
|
||||
timer = setInterval(() => {
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
if (timeList.length > 0) {
|
||||
let totalBytes = timeList.reduce((sum, bytes) => sum + bytesReceivedPerSecond[bytes], 0) / (5 * 1024);
|
||||
let unit = 'KB/s';
|
||||
if (totalBytes > 1024) {
|
||||
totalBytes = totalBytes / 1024;
|
||||
unit = "MB/s";
|
||||
}
|
||||
store.state.trials.downloadTip = totalBytes.toFixed(3) + unit;
|
||||
}
|
||||
if (timeList.length >= 5) {
|
||||
delete bytesReceivedPerSecond[timeList[0]]
|
||||
}
|
||||
let time = new Date().getTime();
|
||||
bytesReceivedPerSecond[time] = 0;
|
||||
}, 1000)
|
||||
|
||||
}
|
||||
export function setNetWorkSpeedSize(totalPercentage, total, Id) {
|
||||
if (imageId && imageId !== Id) return false
|
||||
imageId = Id
|
||||
let percentage = totalPercentage - lastPercentage
|
||||
percentage = percentage / 100
|
||||
lastPercentage = totalPercentage
|
||||
// console.log(percentage, totalPercentage, total)
|
||||
let time = new Date().getTime();
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
let bytesTime = timeList.find(item => time - item < 1000);
|
||||
if (bytesTime) {
|
||||
bytesReceivedPerSecond[bytesTime] += total * percentage;
|
||||
} else {
|
||||
// console.log("未查询到时间")
|
||||
if (timeList.length > 0) {
|
||||
bytesReceivedPerSecond[timeList[timeList.length - 1]] += total * percentage;
|
||||
} else {
|
||||
bytesReceivedPerSecond[time] = total * percentage;
|
||||
}
|
||||
}
|
||||
store.state.trials.uploadSize = `${formatSize(totalPercentage / 100 * total)}/${formatSize(total)}`
|
||||
}
|
||||
export function setNetWorkSpeedSizeAll(totalPercentage, total, Id) {
|
||||
if (!percentageById[Id]) {
|
||||
percentageById[Id] = 0
|
||||
}
|
||||
let percentage = totalPercentage - percentageById[Id]
|
||||
percentage = percentage / 100
|
||||
percentageById[Id] = totalPercentage
|
||||
// console.log(percentage, totalPercentage, total)
|
||||
let time = new Date().getTime();
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
let bytesTime = timeList.find(item => time - item < 1000);
|
||||
if (bytesTime) {
|
||||
bytesReceivedPerSecond[bytesTime] += total * percentage;
|
||||
} else {
|
||||
// console.log("未查询到时间")
|
||||
if (timeList.length > 0) {
|
||||
bytesReceivedPerSecond[timeList[timeList.length - 1]] += total * percentage;
|
||||
} else {
|
||||
bytesReceivedPerSecond[time] = total * percentage;
|
||||
}
|
||||
}
|
||||
let isComplete = Object.keys(percentageById).every(key => percentageById[key >= 100])
|
||||
if (isComplete) {
|
||||
workSpeedclose(true)
|
||||
}
|
||||
}
|
||||
export function workSpeedclose(isForce = false) {
|
||||
if (!isForce && lastPercentage < 100) {
|
||||
return false
|
||||
}
|
||||
console.log('workSpeedclose')
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
store.state.trials.downloadTip = '0KB/s'
|
||||
store.state.trials.downloadSize = ''
|
||||
}
|
||||
bytesReceivedPerSecond = {};
|
||||
lastPercentage = 0;
|
||||
imageId = null;
|
||||
percentageById = {};
|
||||
}
|
||||
+23
-1
@@ -1,6 +1,7 @@
|
||||
import streamSaver from "streamsaver";
|
||||
import "streamsaver/examples/zip-stream.js";
|
||||
import store from '@/store'
|
||||
import dcmjs from './dcmUpload/dcmjs'
|
||||
streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0`
|
||||
// 下载文件并压缩
|
||||
function zipFiles(zipName, files) {
|
||||
@@ -19,7 +20,10 @@ function zipFiles(zipName, files) {
|
||||
if (fileInfo.done) {//迭代终止
|
||||
ctrl.close();
|
||||
} else {
|
||||
let { name, url } = fileInfo.value;
|
||||
let { name, url, IsEncapsulated = false } = fileInfo.value;
|
||||
if (IsEncapsulated) {
|
||||
url = await downloadFileToUrl(url)
|
||||
}
|
||||
// url = decodeUtf8(url); // 待定,可能做过特殊处理
|
||||
return fetch(url).then(res => {
|
||||
ctrl.enqueue({
|
||||
@@ -99,6 +103,24 @@ function decodeUtf8(bytes) {
|
||||
str2.pop();
|
||||
return str2.join("/") + '/' + name;
|
||||
}
|
||||
// 下载文件进行修改并输出本地url
|
||||
function downloadFileToUrl(url) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', url);
|
||||
xhr.responseType = 'arraybuffer';
|
||||
xhr.onload = function () {
|
||||
const arraybuffer = xhr.response;
|
||||
let dataset = dcmjs.data.DicomMessage.readFile(arraybuffer)
|
||||
let newDicomFile = dataset.write({ fragmentMultiframe: false, startOffset: false }) // fragmentMultiframe 原始数据是否进行分割
|
||||
const bufferArray = new Uint8Array(newDicomFile)
|
||||
const blob = new Blob([bufferArray], { type: 'application/octet-stream' })
|
||||
const href = URL.createObjectURL(blob)
|
||||
resolve(href)
|
||||
};
|
||||
xhr.send();
|
||||
})
|
||||
}
|
||||
export async function downLoadFile(file, name, type = 'file') {
|
||||
if (type === 'zip') return await zipFiles(name, file);
|
||||
return await updateFile(file, name)
|
||||
|
||||
@@ -179,7 +179,8 @@ export default {
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
// type: 'email',
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: 'Please input the correct email address',
|
||||
trigger: ['blur'],
|
||||
},
|
||||
|
||||
@@ -19,14 +19,9 @@
|
||||
</div>
|
||||
<div class="viewerSidethumbs ps" style="position: relative;">
|
||||
<div class="viewerSidethumbinner">
|
||||
<div
|
||||
v-for="(item, index) in seriesList"
|
||||
:key="index"
|
||||
:class="{'viewerSideActive': index==0}"
|
||||
<div v-for="(item, index) in seriesList" :key="index" :class="{ 'viewerSideActive': index == 0 }"
|
||||
style="position: relative;margin-bottom:5px;border-radius: 2px;border: 1px solid #404040;"
|
||||
series-type="current"
|
||||
@click="showSeriesImage($event,index,item)"
|
||||
>
|
||||
series-type="current" @click="showSeriesImage($event, index, item)">
|
||||
<div class="viewernavigatorwrapper">
|
||||
<!-- <el-image
|
||||
class="image-preview"
|
||||
@@ -34,14 +29,8 @@
|
||||
:src="item.previewImageUrl"
|
||||
fit="fill"
|
||||
/> -->
|
||||
<img
|
||||
class="image-preview"
|
||||
:src="item.previewImageUrl"
|
||||
crossorigin="anonymous"
|
||||
alt=""
|
||||
style="width: 72px;height:72px;"
|
||||
fit="fill"
|
||||
>
|
||||
<img class="image-preview" :src="item.previewImageUrl" crossorigin="anonymous" alt=""
|
||||
style="width: 72px;height:72px;" fit="fill">
|
||||
<div class="viewernavitextwrapper">
|
||||
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
|
||||
<div v-if="item.keySeries" style="color:red">
|
||||
@@ -51,23 +40,17 @@
|
||||
#{{ item.seriesNumber }}
|
||||
</div>
|
||||
<div v-if="item.isExistMutiFrames && item.instanceCount > 1">
|
||||
<el-popover
|
||||
v-model="item.isShowPopper"
|
||||
placement="right-start"
|
||||
trigger="manual"
|
||||
popper-class="instance_frame_wrapper"
|
||||
>
|
||||
<el-popover v-model="item.isShowPopper" placement="right-start" trigger="manual"
|
||||
popper-class="instance_frame_wrapper">
|
||||
<div style="text-align: right;">
|
||||
<i class="el-icon-circle-close" style="font-size: 20px;cursor: pointer;color:#ddd;" @click="item.isShowPopper = false" />
|
||||
<i class="el-icon-circle-close" style="font-size: 20px;cursor: pointer;color:#ddd;"
|
||||
@click="item.isShowPopper = false" />
|
||||
</div>
|
||||
<div class="frame_list">
|
||||
<div
|
||||
v-for="(instance, idx) in item.instanceInfoList"
|
||||
:key="instance.Id"
|
||||
<div v-for="(instance, idx) in item.instanceInfoList" :key="instance.Id"
|
||||
class="frame_content"
|
||||
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
|
||||
@click="showMultiFrames(item, index, instance)"
|
||||
>
|
||||
:style="{ 'margin-bottom': idx < item.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||
@click="showMultiFrames(item, index, instance)">
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>
|
||||
@@ -75,22 +58,17 @@
|
||||
</div>
|
||||
<div v-if="showDelete">
|
||||
<span>{{ $t('trials:audit:table:isDelete') }}</span>
|
||||
<el-switch
|
||||
v-model="instance.IsDeleted"
|
||||
size="mini"
|
||||
@change="changeInstanceDeleteStatus($event, item, instance)"
|
||||
/>
|
||||
<el-switch v-model="instance.IsDeleted" size="mini"
|
||||
@change="changeInstanceDeleteStatus($event, item, instance)" />
|
||||
<span style="margin-left:10px;">{{ $t('trials:audit:table:isReading') }}</span>
|
||||
<el-switch
|
||||
v-model="instance.IsReading"
|
||||
size="mini"
|
||||
@change="changeInstanceReadingStatus($event, item, instance)"
|
||||
/>
|
||||
<el-switch v-model="instance.IsReading" size="mini"
|
||||
@change="changeInstanceReadingStatus($event, item, instance)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" @click="popperClick(seriesList, item)" />
|
||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;"
|
||||
@click="popperClick(seriesList, item)" />
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
@@ -100,7 +78,8 @@
|
||||
<div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;">
|
||||
T: {{ parseFloat(item.sliceThickness).toFixed(2) }}
|
||||
</div>
|
||||
<div v-show="!item.keySeries &&item.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
<div v-show="!item.keySeries && item.description"
|
||||
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
{{ item.description }}
|
||||
</div>
|
||||
<div v-if="!item.keySeries" style="padding: 1px;">
|
||||
@@ -109,27 +88,23 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
|
||||
<div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;"
|
||||
@click.stop="">
|
||||
|
||||
<div>
|
||||
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') }}</span>
|
||||
<el-switch
|
||||
v-model="item.isReading"
|
||||
size="mini"
|
||||
@change="changeReadingStatus($event, item)"
|
||||
/>
|
||||
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading')
|
||||
}}</span>
|
||||
<el-switch v-model="item.isReading" size="mini" @change="changeReadingStatus($event, item)" />
|
||||
</div>
|
||||
<div>
|
||||
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isDelete') }}</span>
|
||||
<el-switch
|
||||
v-model="item.isDeleted"
|
||||
size="mini"
|
||||
@change="changeDeleteStatus($event, item)"
|
||||
/>
|
||||
<el-switch v-model="item.isDeleted" size="mini" @change="changeDeleteStatus($event, item)" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount * 100">
|
||||
<el-progress :percentage="parseInt((item.prefetchInstanceCount/item.instanceCount).toFixed(2))" />
|
||||
<div
|
||||
v-if="item.prefetchInstanceCount > 0 && item.prefetchInstanceCount < item.instanceCount * 100">
|
||||
<el-progress
|
||||
:percentage="parseInt((item.prefetchInstanceCount / item.instanceCount).toFixed(2))" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -164,6 +139,7 @@ import requestPoolManager from '@/utils/request-pool'
|
||||
import store from '@/store'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import metaDataProvider from '@/utils/metaDataProvider'
|
||||
import { getNetWorkSpeed, setNetWorkSpeedSize, workSpeedclose } from "@/utils"
|
||||
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 })
|
||||
var config = {
|
||||
maxWebWorkers: 4,
|
||||
@@ -184,7 +160,7 @@ export default {
|
||||
'dicom-viewer': dicomViewer
|
||||
},
|
||||
|
||||
data: function() {
|
||||
data: function () {
|
||||
return {
|
||||
trialId: '',
|
||||
studyId: '',
|
||||
@@ -216,10 +192,13 @@ export default {
|
||||
imageList: [],
|
||||
showSeriesList: [],
|
||||
currentLoadIns: [],
|
||||
isFromCRCUpload: false
|
||||
isFromCRCUpload: false,
|
||||
isReading: null,
|
||||
activeSeriesId: null,
|
||||
isPacs: false
|
||||
}
|
||||
},
|
||||
created: function() {
|
||||
created: function () {
|
||||
requestPoolManager.resetRequestPool()
|
||||
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
|
||||
|
||||
@@ -230,6 +209,12 @@ export default {
|
||||
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
|
||||
changeURLStatic('TokenKey', '')
|
||||
}
|
||||
if (this.$router.currentRoute.query.isReading) {
|
||||
this.isReading = this.$router.currentRoute.query.isReading
|
||||
}
|
||||
if (this.$router.currentRoute.query.isPacs) {
|
||||
this.isPacs = Boolean(this.$router.currentRoute.query.isPacs)
|
||||
}
|
||||
this.studyId = this.$router.currentRoute.query.studyId
|
||||
this.isFromCRCUpload = !!this.$router.currentRoute.query.isFromCRCUpload
|
||||
if (this.type === 'Series') {
|
||||
@@ -256,10 +241,15 @@ export default {
|
||||
cornerstone.imageCache.purgeCache()
|
||||
requestPoolManager.resetRequestPool()
|
||||
})
|
||||
workSpeedclose(true)
|
||||
},
|
||||
methods: {
|
||||
async loadStudy() {
|
||||
const data = await getStudyInfo(this.studyId)
|
||||
let params = {}
|
||||
if (this.isPacs) {
|
||||
params.IsPacs = true
|
||||
}
|
||||
const data = await getStudyInfo(this.studyId, params)
|
||||
if (data.IsSuccess) {
|
||||
if (data.Result) {
|
||||
this.studyCode = data.Result.StudyCode
|
||||
@@ -267,7 +257,13 @@ export default {
|
||||
this.seriesCount = data.Result.SeriesCount
|
||||
this.description = data.Result.Description
|
||||
}
|
||||
const url = `/series/list/${this.studyId}`
|
||||
let isReading = !!this.isReading ? `?IsReading=true` : ''
|
||||
if (isReading && this.isPacs) {
|
||||
isReading += `&IsPacs=true`
|
||||
} else if (!isReading && this.isPacs) {
|
||||
isReading = `?IsPacs=true`
|
||||
}
|
||||
const url = `/series/list/${this.studyId}${isReading}`
|
||||
this.getSeriesList(url)
|
||||
}
|
||||
},
|
||||
@@ -317,7 +313,9 @@ export default {
|
||||
loadStatus: false,
|
||||
imageloadedArr: [],
|
||||
isExistMutiFrames: item.IsExistMutiFrames,
|
||||
isShowPopper: false
|
||||
isShowPopper: false,
|
||||
subjectCode: item.SubjectCode,
|
||||
visitName: item.VisitName
|
||||
})
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
@@ -377,7 +375,9 @@ export default {
|
||||
loadStatus: false,
|
||||
imageloadedArr: [],
|
||||
isExistMutiFrames: item.IsExistMutiFrames,
|
||||
isShowPopper: false
|
||||
isShowPopper: false,
|
||||
subjectCode: item.SubjectCode,
|
||||
visitName: item.VisitName
|
||||
})
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
@@ -447,7 +447,9 @@ export default {
|
||||
loadStatus: false,
|
||||
imageloadedArr: [],
|
||||
isExistMutiFrames: isExistMutiFrames,
|
||||
isShowPopper: false
|
||||
isShowPopper: false,
|
||||
subjectCode: res.OtherInfo.SubjectCode,
|
||||
visitName: res.OtherInfo.VisitName
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
if (this.seriesList.length > 0) {
|
||||
@@ -462,6 +464,8 @@ export default {
|
||||
}
|
||||
},
|
||||
showSeriesImage(e, seriesIndex, series) {
|
||||
this.activeSeriesId = series.seriesId
|
||||
workSpeedclose(true)
|
||||
// if (seriesIndex === this.currentSeriesIndex) return
|
||||
const element = e.currentTarget
|
||||
const elements = document.querySelectorAll('[series-type]')
|
||||
@@ -531,7 +535,9 @@ export default {
|
||||
isReading: series.isReading,
|
||||
isDeleted: series.isDeleted,
|
||||
previewImageUrl: series.previewImageUrl,
|
||||
instanceCount: series.instanceCount
|
||||
instanceCount: series.instanceCount,
|
||||
subjectCode: series.SubjectCode,
|
||||
visitName: series.VisitName
|
||||
}
|
||||
this.$refs.dicomViewer.loadImageStack(seriesInfo)
|
||||
if (!series.loadStatus) {
|
||||
@@ -597,7 +603,9 @@ export default {
|
||||
keySeries: seriesInfo.KeySeries,
|
||||
loadStatus: false,
|
||||
imageloadedArr: [],
|
||||
isShowPopper: false
|
||||
isShowPopper: false,
|
||||
subjectCode: seriesInfo.SubjectCode,
|
||||
visitName: seriesInfo.VisitName
|
||||
})
|
||||
this.seriesList = seriesList
|
||||
if (this.seriesList.length > 0) {
|
||||
@@ -851,6 +859,9 @@ export default {
|
||||
const seriesIndex = params.seriesIndex
|
||||
var prefetchInstanceCount = this.seriesList[seriesIndex].prefetchInstanceCount
|
||||
var instanceCount = this.seriesList[seriesIndex].instanceCount
|
||||
if (!this.activeSeriesId) {
|
||||
this.activeSeriesId = this.seriesList[seriesIndex].seriesId
|
||||
}
|
||||
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0 && this.seriesList[seriesIndex].imageloadedArr.length < this.seriesList[seriesIndex].instanceCount) {
|
||||
const i = this.currentLoadIns.findIndex(i => i.imageId === imageId)
|
||||
if (i > -1) {
|
||||
@@ -870,10 +881,16 @@ export default {
|
||||
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
|
||||
}
|
||||
}
|
||||
let file = this.seriesList[seriesIndex].instanceInfoList.find(item => item.ImageId === imageId)
|
||||
if (file && this.activeSeriesId === this.seriesList[seriesIndex].seriesId) {
|
||||
getNetWorkSpeed()
|
||||
setNetWorkSpeedSize(percentComplete, e.detail.total, imageId)
|
||||
}
|
||||
if (prefetchInstanceCount >= instanceCount * 100) {
|
||||
this.seriesList[seriesIndex].prefetchInstanceCount = instanceCount * 100
|
||||
// 设置当前序列状态为已下载完成
|
||||
this.seriesList[seriesIndex].loadStatus = true
|
||||
workSpeedclose()
|
||||
if (!this.isFromCRCUpload) {
|
||||
this.loadAllImages()
|
||||
}
|
||||
@@ -881,90 +898,102 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.viewerContainer .el-tabs--border-card{
|
||||
background:none;
|
||||
.viewerContainer .el-tabs--border-card {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
.viewerContainer .el-tabs__item{
|
||||
|
||||
.viewerContainer .el-tabs__item {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.viewerContainer .el-tabs--border-card>.el-tabs__content{
|
||||
|
||||
.viewerContainer .el-tabs--border-card>.el-tabs__content {
|
||||
padding: 5px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.viewerContainer ::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
.viewerContainer ::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.viewerContainer .relationVisit{
|
||||
|
||||
.viewerContainer .relationVisit {
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerContainer{
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #444;
|
||||
overflow: hidden;
|
||||
}
|
||||
.viewerContainer .viewerBanner {
|
||||
background: linear-gradient(0,#444,#222);
|
||||
min-height: 28px;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-top: 0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
|
||||
.viewerContainer {
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #444;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerBanner {
|
||||
background: linear-gradient(0, #444, #222);
|
||||
min-height: 28px;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-top: 0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
/* height: 95%; */
|
||||
height: 99%;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
/* height: 95%; */
|
||||
height: 99%;
|
||||
overflow: hidden;
|
||||
text-overflow: clip;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper>div {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel {
|
||||
width: 215px;
|
||||
background-color: #323232;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
color: #D0D0D0;
|
||||
overflow-y: auto;
|
||||
width: 215px;
|
||||
background-color: #323232;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
color: #D0D0D0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper>div>.sidePanelBody {
|
||||
background: rgba(50,50,50,1);
|
||||
word-break: break-all;
|
||||
display: table;
|
||||
width: 100%;
|
||||
border: 1px solid #3e3f3a;
|
||||
background: rgba(50, 50, 50, 1);
|
||||
word-break: break-all;
|
||||
display: table;
|
||||
width: 100%;
|
||||
border: 1px solid #3e3f3a;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper>div>div.sidePanelBody>div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.viewerContainer .studyDesc{
|
||||
|
||||
.viewerContainer .studyDesc {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
@@ -972,81 +1001,96 @@ export default {
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.viewerContainer .ps {
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
|
||||
display: flex;
|
||||
width: 200px;
|
||||
height: 84px;
|
||||
padding: 1px 2px 1px 8px;
|
||||
margin: 6px 0 6px 1px;
|
||||
/* border-radius: 2px;
|
||||
display: flex;
|
||||
width: 200px;
|
||||
height: 84px;
|
||||
padding: 1px 2px 1px 8px;
|
||||
margin: 6px 0 6px 1px;
|
||||
/* border-radius: 2px;
|
||||
border: 1px solid #404040; */
|
||||
}
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress__text{
|
||||
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress__text {
|
||||
display: none;
|
||||
}
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress-bar{
|
||||
padding-right:0px;
|
||||
}
|
||||
.viewerContainer .ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .image-preview {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavitextwrapper {
|
||||
/* width: 120px;
|
||||
height: 80px; */
|
||||
flex:1;
|
||||
padding: 3px 1px 3px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
||||
width: 20px;
|
||||
|
||||
font-size: 12px;
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress-bar {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.viewerContainer .ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .image-preview {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavitextwrapper {
|
||||
/* width: 120px;
|
||||
height: 80px; */
|
||||
flex: 1;
|
||||
padding: 3px 1px 3px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
||||
width: 20px;
|
||||
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerSideActive {
|
||||
background: #16477b;
|
||||
background: #16477b80;
|
||||
border: 1px solid #23527b;
|
||||
background: #16477b;
|
||||
background: #16477b80;
|
||||
border: 1px solid #23527b;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContent {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: black;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: black;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.instance_frame_wrapper{
|
||||
|
||||
.instance_frame_wrapper {
|
||||
min-width: 120px;
|
||||
background-color: #2c2c2c;
|
||||
border: 1px solid #2c2c2c;
|
||||
padding: 5px;
|
||||
}
|
||||
.frame_list{
|
||||
|
||||
.frame_list {
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.instance_frame_wrapper ::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
|
||||
|
||||
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.frame_content{
|
||||
|
||||
.frame_content {
|
||||
/* height: 50px; */
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
@@ -1055,6 +1099,7 @@ export default {
|
||||
font-size: 12px;
|
||||
border: 1px solid #404040;
|
||||
}
|
||||
|
||||
.frame_content:hover {
|
||||
/* font-weight: bold; */
|
||||
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
|
||||
@@ -1063,6 +1108,7 @@ export default {
|
||||
border-color: #213a54 !important;
|
||||
background-color: #213a54;
|
||||
}
|
||||
|
||||
/* .viewerRightSidePanel {
|
||||
width: 300px;
|
||||
height: 100%;
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
:key="index"
|
||||
> -->
|
||||
<el-collapse v-model="activeNames">
|
||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`"
|
||||
:name="`${study.StudyId}`">
|
||||
<template slot="title">
|
||||
|
||||
<div class="text-desc">
|
||||
@@ -25,8 +26,10 @@
|
||||
<!-- <div v-show="study.Description" class="text-desc">
|
||||
{{ study.Description }}
|
||||
</div> -->
|
||||
<el-tooltip v-show="study.Description" class="item" effect="dark" :content="study.Description" placement="bottom">
|
||||
<div v-show="study.Description" style="width: 50px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
<el-tooltip v-show="study.Description" class="item" effect="dark" :content="study.Description"
|
||||
placement="bottom">
|
||||
<div v-show="study.Description"
|
||||
style="width: 50px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
{{ study.Description }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
@@ -37,44 +40,29 @@
|
||||
<div v-show="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
||||
{{ study.Description }}
|
||||
</div>
|
||||
<div
|
||||
v-for="(series, i) in study.SeriesList"
|
||||
:key="i"
|
||||
:class="{'viewerSideActive': i==0 && index === 0}"
|
||||
<div v-for="(series, i) in study.SeriesList" :key="i"
|
||||
:class="{ 'viewerSideActive': i == 0 && index === 0 }"
|
||||
style="position: relative;margin-bottom:5px;border-radius: 2px;border: 1px solid #404040;"
|
||||
series-type="current"
|
||||
@click="showSeriesImage($event,index,i,series)"
|
||||
>
|
||||
series-type="current" @click="showSeriesImage($event, index, i, series)">
|
||||
<div class="viewernavigatorwrapper">
|
||||
<img
|
||||
class="image-preview"
|
||||
:src="series.previewImageUrl"
|
||||
crossorigin="anonymous"
|
||||
alt=""
|
||||
style="width: 85px;height:85px;"
|
||||
fit="fill"
|
||||
>
|
||||
<img class="image-preview" :src="series.previewImageUrl" crossorigin="anonymous" alt=""
|
||||
style="width: 85px;height:85px;" fit="fill">
|
||||
<div class="viewernavitextwrapper">
|
||||
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
|
||||
<div>#{{ series.seriesNumber }}</div>
|
||||
<div v-if="series.isExistMutiFrames && series.instanceCount > 1">
|
||||
<el-popover
|
||||
v-model="series.isShowPopper"
|
||||
placement="right-start"
|
||||
trigger="manual"
|
||||
popper-class="instance_frame_wrapper"
|
||||
>
|
||||
<el-popover v-model="series.isShowPopper" placement="right-start" trigger="manual"
|
||||
popper-class="instance_frame_wrapper">
|
||||
<div style="text-align: right;">
|
||||
<i class="el-icon-circle-close" style="font-size: 20px;cursor: pointer;color:#ddd;" @click="series.isShowPopper = false" />
|
||||
<i class="el-icon-circle-close"
|
||||
style="font-size: 20px;cursor: pointer;color:#ddd;"
|
||||
@click="series.isShowPopper = false" />
|
||||
</div>
|
||||
<div class="frame_list">
|
||||
<div
|
||||
v-for="(instance, idx) in series.instanceInfoList"
|
||||
:key="instance.Id"
|
||||
<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="showMultiFrames(index,series, i, instance)"
|
||||
>
|
||||
:style="{ 'margin-bottom': idx < series.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||
@click="showMultiFrames(index, series, i, instance)">
|
||||
<!-- <div>
|
||||
<img
|
||||
class="image-preview"
|
||||
@@ -92,23 +80,20 @@
|
||||
</div>
|
||||
<div v-if="showDelete">
|
||||
<span>{{ $t('trials:audit:table:isDelete') }}</span>
|
||||
<el-switch
|
||||
v-model="instance.IsDeleted"
|
||||
size="mini"
|
||||
@change="changeInstanceDeleteStatus($event, series, instance)"
|
||||
/>
|
||||
<span style="margin-left:10px;">{{ $t('trials:audit:table:isReading') }}</span>
|
||||
<el-switch
|
||||
v-model="instance.IsReading"
|
||||
size="mini"
|
||||
@change="changeInstanceReadingStatus($event, series, instance)"
|
||||
/>
|
||||
<el-switch v-model="instance.IsDeleted" size="mini"
|
||||
@change="changeInstanceDeleteStatus($event, series, instance)" />
|
||||
<span style="margin-left:10px;">{{ $t('trials:audit:table:isReading')
|
||||
}}</span>
|
||||
<el-switch v-model="instance.IsReading" size="mini"
|
||||
@change="changeInstanceReadingStatus($event, series, instance)" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" @click="popperClick(studyList, series)" />
|
||||
<i slot="reference" class="el-icon-connection"
|
||||
style="font-size: 15px;cursor: pointer;"
|
||||
@click="popperClick(studyList, series)" />
|
||||
</el-popover>
|
||||
</div>
|
||||
|
||||
@@ -116,12 +101,14 @@
|
||||
<div v-show="series.InstanceCount" style="padding: 1px;">
|
||||
{{ series.modality }}: {{ series.instanceCount }} image
|
||||
</div>
|
||||
<div v-show=" series.sliceThickness" style="padding: 1px;">
|
||||
<div v-show="series.sliceThickness" style="padding: 1px;">
|
||||
T: {{ series.sliceThickness }}
|
||||
</div>
|
||||
|
||||
<el-tooltip v-show="series.description" class="item" effect="dark" :content="series.description" placement="bottom">
|
||||
<div v-show="series.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
<el-tooltip v-show="series.description" class="item" effect="dark"
|
||||
:content="series.description" placement="bottom">
|
||||
<div v-show="series.description"
|
||||
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
{{ series.description }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
@@ -131,30 +118,27 @@
|
||||
<div />
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
|
||||
<div v-if="showDelete"
|
||||
style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
|
||||
|
||||
<div>
|
||||
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span>
|
||||
<el-switch
|
||||
v-model="series.isReading"
|
||||
size="mini"
|
||||
@change="changeReadingStatus($event, series)"
|
||||
/>
|
||||
<el-switch v-model="series.isReading" size="mini"
|
||||
@change="changeReadingStatus($event, series)" />
|
||||
</div>
|
||||
<div>
|
||||
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span>
|
||||
<el-switch
|
||||
v-model="series.isDeleted"
|
||||
size="mini"
|
||||
@change="changeDeleteStatus($event, series)"
|
||||
/>
|
||||
<el-switch v-model="series.isDeleted" size="mini"
|
||||
@change="changeDeleteStatus($event, series)" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div style="position: absolute;bottom: -10px;left: 0;width: 100%;">
|
||||
<el-progress v-if="series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" :percentage="Number(series.prefetchInstanceCount/series.instanceCount)*100" />
|
||||
</div> -->
|
||||
<div v-if="series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount * 100">
|
||||
<el-progress :percentage="parseInt((series.prefetchInstanceCount/series.instanceCount).toFixed(2))" />
|
||||
<div
|
||||
v-if="series.prefetchInstanceCount > 0 && series.prefetchInstanceCount < series.instanceCount * 100">
|
||||
<el-progress
|
||||
:percentage="parseInt((series.prefetchInstanceCount / series.instanceCount).toFixed(2))" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -165,102 +149,109 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane v-if="!visitTaskId" :label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper">
|
||||
<el-tab-pane v-show="!visitTaskId" :label="$t('trials:dicom-show:relatedVisit')" name="relation-study"
|
||||
class="pane-relation-wrapper">
|
||||
<div class="viewerSidethumbinner">
|
||||
<el-collapse v-model="relationActiveName" @change="handelRelationActiveChange">
|
||||
<el-collapse-item v-for="(study,studyIndex) in relationStudyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
||||
<template slot="title">
|
||||
|
||||
<div class="text-desc">
|
||||
{{ study.StudyCode }}
|
||||
<el-collapse v-model="relationActiveName" @change="handelRelationActiveChange">
|
||||
<template v-for="item in relationStudyListByVisitName">
|
||||
<div :key="`${item.VisitName}`">
|
||||
<div v-show="item.VisitName" class="text-desc" style="background-color: #1f1f1f;">
|
||||
{{ item.VisitName }}
|
||||
</div>
|
||||
<!-- <div v-show="study.Description" class="text-desc">
|
||||
<template v-for="(study, studyIndex) in relationStudyList">
|
||||
<el-collapse-item :key="`${study.StudyId}`" :name="`${study.StudyId}`"
|
||||
v-if="study.VisitName === item.VisitName">
|
||||
<template slot="title">
|
||||
|
||||
<div class="text-desc">
|
||||
{{ study.StudyCode }}
|
||||
</div>
|
||||
<!-- <div v-show="study.Description" class="text-desc">
|
||||
{{ study.Description }}
|
||||
</div> -->
|
||||
|
||||
<div v-show="study.SeriesCount" class="text-desc">
|
||||
{{ study.Modalities }} : {{ study.SeriesCount }} Series
|
||||
</div>
|
||||
</template>
|
||||
<div v-show="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
||||
{{ study.Description }}
|
||||
</div>
|
||||
<div v-if="study.seriesList" class="viewerSidethumbs ps" style="position: relative;">
|
||||
<div class="viewerSidethumbinner">
|
||||
<div
|
||||
v-for="(seriesItem, index) in study.seriesList"
|
||||
:key="index"
|
||||
class="viewernavigatorwrapper"
|
||||
style="position: relative;border:1px solid #434343;"
|
||||
series-type="relation"
|
||||
@click="showRelationSeriesImage($event,seriesItem,studyIndex,index)"
|
||||
>
|
||||
<!-- <el-image
|
||||
<div v-show="study.SeriesCount" class="text-desc">
|
||||
{{ study.Modalities }} : {{ study.SeriesCount }} Series
|
||||
</div>
|
||||
</template>
|
||||
<div v-show="study.Description" class="text-desc" style="background-color: #1f1f1f;">
|
||||
{{ study.Description }}
|
||||
</div>
|
||||
<div class="viewerSidethumbs ps" style="position: relative;">
|
||||
<div class="viewerSidethumbinner">
|
||||
<div v-for="(seriesItem, index) in study.seriesList" :key="seriesItem.seriesId">
|
||||
<div class="viewernavigatorwrapper"
|
||||
style="position: relative;border:1px solid #434343;" series-type="relation"
|
||||
@click="showRelationSeriesImage($event, seriesItem, studyIndex, index)">
|
||||
<img class="image-preview" :src="seriesItem.previewImageUrl" crossorigin="anonymous"
|
||||
alt="" style="width: 85px;height:85px;" fit="fill">
|
||||
|
||||
<div class="viewernavitextwrapper">
|
||||
<div
|
||||
style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
|
||||
<div v-if="seriesItem.keySeries" style="color:red">
|
||||
Key Images
|
||||
</div>
|
||||
<div v-else>#{{ seriesItem.seriesNumber }}</div>
|
||||
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
|
||||
<el-popover placement="right-start" trigger="click"
|
||||
popper-class="instance_frame_wrapper">
|
||||
<div class="frame_list">
|
||||
<div v-for="(instance, idx) in seriesItem.instanceInfoList"
|
||||
:key="instance.Id" class="frame_content"
|
||||
:style="{ 'margin-bottom': idx < seriesItem.instanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||
@click="showMultiFrames(studyIndex, seriesItem, index, instance)">
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1}
|
||||
frame`
|
||||
}}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<i slot="reference" class="el-icon-connection"
|
||||
style="font-size: 15px;cursor: pointer;" />
|
||||
</el-popover>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div v-show="seriesItem.instanceCount" style="padding: 1px;">
|
||||
{{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image
|
||||
</div>
|
||||
<div v-show="seriesItem.sliceThickness" style="padding: 1px;">
|
||||
T: {{ seriesItem.sliceThickness }}
|
||||
</div>
|
||||
<el-tooltip v-show="seriesItem.description" class="item" effect="dark"
|
||||
:content="seriesItem.description" placement="bottom">
|
||||
<div v-show="seriesItem.description"
|
||||
style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
{{ seriesItem.description }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <el-image
|
||||
class="image-preview"
|
||||
style="height:72px;width:72px;"
|
||||
:src="seriesItem.previewImageUrl"
|
||||
fit="fill"
|
||||
/> -->
|
||||
<img
|
||||
class="image-preview"
|
||||
:src="seriesItem.previewImageUrl"
|
||||
crossorigin="anonymous"
|
||||
alt=""
|
||||
style="width: 85px;height:85px;"
|
||||
fit="fill"
|
||||
>
|
||||
|
||||
<div class="viewernavitextwrapper">
|
||||
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
|
||||
<div v-if="seriesItem.keySeries" style="color:red">
|
||||
Key Images
|
||||
<div
|
||||
v-if="seriesItem.prefetchInstanceCount > 0 && seriesItem.prefetchInstanceCount < seriesItem.instanceCount * 100">
|
||||
<el-progress
|
||||
:percentage="parseInt((seriesItem.prefetchInstanceCount / seriesItem.instanceCount).toFixed(2))" />
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>#{{ seriesItem.seriesNumber }}</div>
|
||||
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
|
||||
<el-popover
|
||||
placement="right-start"
|
||||
trigger="click"
|
||||
popper-class="instance_frame_wrapper"
|
||||
>
|
||||
<div class="frame_list">
|
||||
<div
|
||||
v-for="(instance, idx) in seriesItem.instanceInfoList"
|
||||
:key="instance.Id"
|
||||
class="frame_content"
|
||||
:style="{'margin-bottom':idx<seriesItem.instanceInfoList.length-1? '5px':'0px'}"
|
||||
@click="showMultiFrames(studyIndex,seriesItem, index, instance)"
|
||||
>
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
|
||||
</el-popover>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div v-show="seriesItem.instanceCount" style="padding: 1px;">
|
||||
{{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image
|
||||
</div>
|
||||
<div v-show="seriesItem.sliceThickness" style="padding: 1px;">
|
||||
T: {{ seriesItem.sliceThickness }}
|
||||
</div>
|
||||
<el-tooltip v-show="seriesItem.description" class="item" effect="dark" :content="seriesItem.description" placement="bottom">
|
||||
<div v-show="seriesItem.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
|
||||
{{ seriesItem.description }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<!-- <div style="position: absolute;bottom: -10px;left: 0;width: 100%;">
|
||||
<el-progress v-if="seriesItem.prefetchInstanceCount>0 && seriesItem.prefetchInstanceCount<seriesItem.instanceCount" :percentage="Number(seriesItem.prefetchInstanceCount/seriesItem.instanceCount)*100" />
|
||||
</div> -->
|
||||
</div>
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</template>
|
||||
|
||||
</div>
|
||||
</el-collapse-item>
|
||||
</template>
|
||||
|
||||
</el-collapse>
|
||||
|
||||
</div>
|
||||
@@ -287,6 +278,7 @@ import { getTaskUploadedDicomStudyList } from '@/api/reading'
|
||||
import requestPoolManager from '@/utils/request-pool'
|
||||
import store from '@/store'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import { getNetWorkSpeed, setNetWorkSpeedSize, workSpeedclose } from "@/utils"
|
||||
import metaDataProvider from '@/utils/metaDataProvider'
|
||||
cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 })
|
||||
// import * as cornerstoneTools from 'cornerstone-tools'
|
||||
@@ -315,6 +307,7 @@ export default {
|
||||
visitInfo: '',
|
||||
activeName: 'current-study',
|
||||
relationStudyList: [],
|
||||
relationStudyListByVisitName: [],
|
||||
cachedImages: [],
|
||||
isReading: null,
|
||||
isStartLoad: false,
|
||||
@@ -328,7 +321,8 @@ export default {
|
||||
currentLoadIns: [],
|
||||
isFromCRCUpload: false,
|
||||
visitTaskId: null,
|
||||
page: ''
|
||||
page: '',
|
||||
activeSeriesId: null
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -361,6 +355,7 @@ export default {
|
||||
cornerstone.imageCache.purgeCache()
|
||||
requestPoolManager.resetRequestPool()
|
||||
})
|
||||
workSpeedclose(true)
|
||||
},
|
||||
methods: {
|
||||
// 获取某个访视下所有的检查信息
|
||||
@@ -369,11 +364,14 @@ export default {
|
||||
try {
|
||||
let res = null
|
||||
if (this.page === 'upload') {
|
||||
res = await getTaskUploadedDicomStudyList({ visitTaskId: this.visitTaskId })
|
||||
} else if (this.page === 'download') {
|
||||
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading, this.visitTaskId)
|
||||
} else {
|
||||
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading)
|
||||
res = await getTaskUploadedDicomStudyList({ visitTaskId: this.visitTaskId !== 'undefined' ? this.visitTaskId : null, subjectVisitId: this.subjectVisitId })
|
||||
}
|
||||
// else if (this.page === 'download') {
|
||||
// res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading, this.visitTaskId)
|
||||
// }
|
||||
else {
|
||||
// res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading)
|
||||
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading, this.visitTaskId !== 'undefined' ? this.visitTaskId : null)
|
||||
}
|
||||
if (res.IsSuccess) {
|
||||
res.Result.forEach((study, studyIndex) => {
|
||||
@@ -422,7 +420,9 @@ export default {
|
||||
loadStatus: false,
|
||||
imageloadedArr: [],
|
||||
isExistMutiFrames: series.IsExistMutiFrames,
|
||||
isShowPopper: false
|
||||
isShowPopper: false,
|
||||
subjectCode: series.SubjectCode,
|
||||
visitName: series.VisitName
|
||||
})
|
||||
})
|
||||
data.SeriesList = seriesList
|
||||
@@ -459,6 +459,8 @@ export default {
|
||||
}
|
||||
},
|
||||
showSeriesImage(e, studyIndex, seriesIndex, series) {
|
||||
this.activeSeriesId = series.seriesId
|
||||
workSpeedclose(true)
|
||||
const element = e.currentTarget
|
||||
const elements = document.querySelectorAll('[series-type]')
|
||||
Array.from(elements).forEach((e) => {
|
||||
@@ -521,7 +523,9 @@ export default {
|
||||
isReading: series.isReading,
|
||||
isDeleted: series.isDeleted,
|
||||
previewImageUrl: series.previewImageUrl,
|
||||
instanceCount: series.instanceCount
|
||||
instanceCount: series.instanceCount,
|
||||
subjectCode: series.SubjectCode,
|
||||
visitName: series.VisitName
|
||||
}
|
||||
this.$refs.dicomViewer.loadImageStack(seriesInfo)
|
||||
if (!series.loadStatus) {
|
||||
@@ -707,10 +711,26 @@ export default {
|
||||
spinner: 'el-icon-loading'
|
||||
})
|
||||
try {
|
||||
const res = await getAllRelationStudyList(this.subjectVisitId)
|
||||
let params = {
|
||||
IsReading: !!this.isReading
|
||||
}
|
||||
const res = await getAllRelationStudyList(this.subjectVisitId, params)
|
||||
loading.close()
|
||||
this.relationStudyList = res.Result
|
||||
this.relationStudyListByVisitName = []
|
||||
res.Result.forEach(item => {
|
||||
let index = this.relationStudyListByVisitName.findIndex(d => d.VisitName === item.VisitName)
|
||||
if (index < 0) {
|
||||
this.relationStudyListByVisitName.push({
|
||||
VisitName: item.VisitName,
|
||||
series: [item]
|
||||
})
|
||||
} else {
|
||||
this.relationStudyListByVisitName[index].series.push(item)
|
||||
}
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loading.close()
|
||||
}
|
||||
}
|
||||
@@ -739,7 +759,8 @@ export default {
|
||||
spinner: 'el-icon-loading'
|
||||
})
|
||||
try {
|
||||
const data = await getSeriesList(`/series/list/${studyId}`)
|
||||
let isReading = !!this.isReading ? `?IsReading=true` : ''
|
||||
const data = await getSeriesList(`/series/list/${studyId}${isReading}`)
|
||||
loading.close()
|
||||
if (data.Result != null && data.Result.length > 0) {
|
||||
var seriesList = []
|
||||
@@ -749,9 +770,15 @@ export default {
|
||||
item.InstanceInfoList.forEach(i => {
|
||||
if (i.NumberOfFrames && i.NumberOfFrames > 1) {
|
||||
for (let j = 0; j < i.NumberOfFrames; j++) {
|
||||
if (!i.ImageId) {
|
||||
i.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&idx=${index}|${seriesIndex}&isRelation=1`
|
||||
}
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&idx=${index}|${seriesIndex}&isRelation=1`)
|
||||
}
|
||||
} else {
|
||||
if (!i.ImageId) {
|
||||
i.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&idx=${index}|${seriesIndex}&isRelation=1`
|
||||
}
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&idx=${index}|${seriesIndex}&isRelation=1`)
|
||||
}
|
||||
})
|
||||
@@ -772,12 +799,17 @@ export default {
|
||||
loadStatus: false,
|
||||
imageloadedArr: [],
|
||||
isExistMutiFrames: item.IsExistMutiFrames,
|
||||
isShowPopper: false
|
||||
isShowPopper: false,
|
||||
subjectCode: item.SubjectCode,
|
||||
visitName: item.VisitName
|
||||
})
|
||||
})
|
||||
scope.relationStudyList[index].seriesCount = seriesList.length
|
||||
scope.relationStudyList[index].seriesList = seriesList
|
||||
scope.relationStudyList[index].showSeries = true
|
||||
// scope.relationStudyList[index].seriesCount = seriesList.length
|
||||
// scope.relationStudyList[index].seriesList = seriesList
|
||||
// scope.relationStudyList[index].showSeries = true
|
||||
scope.$set(scope.relationStudyList[index], 'seriesCount', seriesList.length)
|
||||
scope.$set(scope.relationStudyList[index], 'seriesList', seriesList)
|
||||
scope.$set(scope.relationStudyList[index], 'showSeries', true)
|
||||
scope.$forceUpdate()
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -786,6 +818,8 @@ export default {
|
||||
}
|
||||
},
|
||||
showRelationSeriesImage(e, series, studyIndex, index) {
|
||||
this.activeSeriesId = series.seriesId
|
||||
workSpeedclose(true)
|
||||
this.currentRelationIndex = index
|
||||
const element = e.currentTarget
|
||||
const elements = document.querySelectorAll('[series-type]')
|
||||
@@ -805,6 +839,9 @@ export default {
|
||||
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
|
||||
})
|
||||
}
|
||||
if (this.imageList.length > 0) {
|
||||
this.loopLoad()
|
||||
}
|
||||
}
|
||||
},
|
||||
loadAllImages() {
|
||||
@@ -864,8 +901,11 @@ export default {
|
||||
}
|
||||
const studyIndex = params.idx.split('|')[0]
|
||||
const seriesIndex = params.idx.split('|')[1]
|
||||
var series = !params.isRelation ? this.studyList[studyIndex].SeriesList[seriesIndex] : null
|
||||
var series = !params.isRelation ? this.studyList[studyIndex].SeriesList[seriesIndex] : this.relationStudyList[studyIndex].seriesList[seriesIndex]
|
||||
if (!series) return
|
||||
if (!this.activeSeriesId) {
|
||||
this.activeSeriesId = series.seriesId
|
||||
}
|
||||
var prefetchInstanceCount = series.prefetchInstanceCount
|
||||
var instanceCount = series.instanceCount
|
||||
if (series.imageloadedArr.indexOf(imageId) < 0) {
|
||||
@@ -887,6 +927,11 @@ export default {
|
||||
series.imageloadedArr.push(imageId)
|
||||
}
|
||||
}
|
||||
let file = series.instanceInfoList.find(item => item.ImageId === imageId)
|
||||
if (file && this.activeSeriesId === series.seriesId) {
|
||||
getNetWorkSpeed()
|
||||
setNetWorkSpeedSize(percentComplete, e.detail.total, imageId)
|
||||
}
|
||||
if (prefetchInstanceCount >= instanceCount * 100) {
|
||||
series.prefetchInstanceCount = instanceCount * 100
|
||||
// 设置当前序列状态为已下载完成
|
||||
@@ -894,96 +939,110 @@ export default {
|
||||
if (!this.isFromCRCUpload) {
|
||||
this.loadAllImages()
|
||||
}
|
||||
workSpeedclose()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style >
|
||||
.viewerContainer .el-tabs--border-card{
|
||||
background:none;
|
||||
<style>
|
||||
.viewerContainer .el-tabs--border-card {
|
||||
background: none;
|
||||
border: none;
|
||||
}
|
||||
.viewerContainer .el-tabs__item{
|
||||
|
||||
.viewerContainer .el-tabs__item {
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
width: 100px;
|
||||
padding: 0!important;
|
||||
padding: 0 !important;
|
||||
text-align: center;
|
||||
transform: scale(.8);
|
||||
}
|
||||
.viewerContainer .el-tabs--border-card>.el-tabs__content{
|
||||
|
||||
.viewerContainer .el-tabs--border-card>.el-tabs__content {
|
||||
padding: 5px 0px 0px 0px;
|
||||
}
|
||||
|
||||
.viewerContainer ::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
|
||||
.viewerContainer ::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.viewerContainer .relationVisit{
|
||||
|
||||
.viewerContainer .relationVisit {
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerContainer{
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #444;
|
||||
overflow: hidden;
|
||||
}
|
||||
.viewerContainer .viewerBanner {
|
||||
background: linear-gradient(0,#444,#222);
|
||||
min-height: 28px;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-top: 0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
|
||||
.viewerContainer {
|
||||
display: block;
|
||||
height: 100%;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
background-color: #444;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerBanner {
|
||||
background: linear-gradient(0, #444, #222);
|
||||
min-height: 28px;
|
||||
font-size: 16px;
|
||||
margin: 0;
|
||||
height: 30px;
|
||||
padding-top: 0;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
/* height: 95%; */
|
||||
height: 99%;
|
||||
/* overflow: hidden;
|
||||
width: 100%;
|
||||
padding: 5px;
|
||||
/* height: 95%; */
|
||||
height: 99%;
|
||||
/* overflow: hidden;
|
||||
text-overflow: clip; */
|
||||
/* white-space: nowrap; */
|
||||
/* white-space: nowrap; */
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper>div {
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
display: inline-block;
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel {
|
||||
width: 220px;
|
||||
background-color: #323232;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
color: #D0D0D0;
|
||||
overflow-y: auto;
|
||||
width: 220px;
|
||||
background-color: #323232;
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
margin-right: 2px;
|
||||
color: #D0D0D0;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper>div>.sidePanelBody {
|
||||
background: rgba(50,50,50,1);
|
||||
word-break: break-all;
|
||||
display: table;
|
||||
width: 100%;
|
||||
border: 1px solid #3e3f3a;
|
||||
background: rgba(50, 50, 50, 1);
|
||||
word-break: break-all;
|
||||
display: table;
|
||||
width: 100%;
|
||||
border: 1px solid #3e3f3a;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContentWrapper>div>div.sidePanelBody>div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.viewerContainer .text-desc{
|
||||
|
||||
.viewerContainer .text-desc {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
@@ -991,107 +1050,126 @@ export default {
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.viewerContainer .ps {
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
overflow: hidden !important;
|
||||
overflow-anchor: none;
|
||||
-ms-overflow-style: none;
|
||||
touch-action: auto;
|
||||
-ms-touch-action: auto;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavigatorwrapper {
|
||||
display: flex;
|
||||
width: 220px;
|
||||
/* height: 84px; */
|
||||
padding: 1px 2px 1px 2px;
|
||||
margin: 2px 0 1px 1px;
|
||||
/* border-radius: 2px;
|
||||
display: flex;
|
||||
width: 220px;
|
||||
/* height: 84px; */
|
||||
padding: 1px 2px 1px 2px;
|
||||
margin: 2px 0 1px 1px;
|
||||
/* border-radius: 2px;
|
||||
border: 1px solid #404040; */
|
||||
|
||||
}
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress__text{
|
||||
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress__text {
|
||||
display: none;
|
||||
}
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress-bar{
|
||||
padding-right:0px;
|
||||
}
|
||||
.viewerContainer .ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .image-preview {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavitextwrapper {
|
||||
/* width: 120px;
|
||||
height: 80px; */
|
||||
flex:1;
|
||||
padding: 3px 1px 3px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
}
|
||||
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
||||
width: 20px;
|
||||
|
||||
font-size: 12px;
|
||||
.viewerContainer .viewernavigatorwrapper .el-progress-bar {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.viewerContainer .ui-draggable-handle {
|
||||
-ms-touch-action: none;
|
||||
touch-action: none;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .image-preview {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .viewernavitextwrapper {
|
||||
/* width: 120px;
|
||||
height: 80px; */
|
||||
flex: 1;
|
||||
padding: 3px 1px 3px 4px;
|
||||
vertical-align: top;
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerLeftSidePanel .viewerlabelwrapper {
|
||||
width: 20px;
|
||||
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerSideActive {
|
||||
background: #16477b;
|
||||
background: #16477b80;
|
||||
border: 1px solid #23527b;
|
||||
background: #16477b;
|
||||
background: #16477b80;
|
||||
border: 1px solid #23527b;
|
||||
}
|
||||
|
||||
.viewerContainer .viewerContent {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: black;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
display: block;
|
||||
background-color: black;
|
||||
color: #D0D0D0;
|
||||
font-size: 13px;
|
||||
}
|
||||
.viewerContainer .pane-relation-wrapper{
|
||||
|
||||
.viewerContainer .pane-relation-wrapper {
|
||||
min-height: 500px;
|
||||
}
|
||||
.viewerContainer .el-collapse{
|
||||
|
||||
.viewerContainer .el-collapse {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.viewerContainer .el-collapse-item{
|
||||
background-color: #585453!important;
|
||||
.viewerContainer .el-collapse-item {
|
||||
background-color: #585453 !important;
|
||||
color: #ddd;
|
||||
|
||||
}
|
||||
.viewerContainer .el-collapse-item__content{
|
||||
padding-bottom:5px;
|
||||
background-color: #2c2c2c!important;
|
||||
|
||||
.viewerContainer .el-collapse-item__content {
|
||||
padding-bottom: 5px;
|
||||
background-color: #2c2c2c !important;
|
||||
color: #ddd;
|
||||
}
|
||||
.viewerContainer .el-collapse-item__header{
|
||||
background-color: #585453!important;
|
||||
|
||||
.viewerContainer .el-collapse-item__header {
|
||||
background-color: #585453 !important;
|
||||
color: #ddd;
|
||||
border-bottom-color:#5a5a5a;
|
||||
border-bottom-color: #5a5a5a;
|
||||
padding-left: 5px;
|
||||
height: 40px;
|
||||
line-height: 20px;
|
||||
}
|
||||
.instance_frame_wrapper{
|
||||
|
||||
.instance_frame_wrapper {
|
||||
min-width: 120px;
|
||||
background-color: #2c2c2c;
|
||||
border: 1px solid #2c2c2c;
|
||||
padding: 5px;
|
||||
}
|
||||
.frame_list{
|
||||
|
||||
.frame_list {
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.instance_frame_wrapper ::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
|
||||
|
||||
.instance_frame_wrapper ::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.frame_content{
|
||||
|
||||
.frame_content {
|
||||
/* height: 50px; */
|
||||
padding: 10px;
|
||||
display: flex;
|
||||
@@ -1100,6 +1178,7 @@ export default {
|
||||
font-size: 12px;
|
||||
border: 1px solid #404040;
|
||||
}
|
||||
|
||||
.frame_content:hover {
|
||||
/* font-weight: bold; */
|
||||
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
|
||||
@@ -1121,4 +1200,3 @@ export default {
|
||||
font-size: 13px;
|
||||
} */
|
||||
</style>
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ 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 mp4 from '@/assets/file_icon/mp4.png'
|
||||
import PreviewFile from '@/components/PreviewFile'
|
||||
import imageViewer from './image-viewer'
|
||||
import { getSystemDocumentAttachmentList } from '@/api/dictionary'
|
||||
@@ -117,6 +118,7 @@ export default {
|
||||
pptx,
|
||||
xls,
|
||||
xlsx,
|
||||
mp4,
|
||||
rowData: {},
|
||||
list: [],
|
||||
searchData: defaultSearchData(),
|
||||
|
||||
@@ -0,0 +1,269 @@
|
||||
<template>
|
||||
<el-form ref="sysTemplateFrom" v-loading="loading" :model="form" label-width="140px" size="small" :rules="rules"
|
||||
class="upload-temporary-file">
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item :label="$t('dictionary:attachment:label:code')" prop="Code">
|
||||
<el-input v-model="form.Code" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:attachment:label:businessScenario')" prop="BusinessScenarioEnum">
|
||||
<el-select v-model="form.BusinessScenarioEnum" style="width: 100%" size="small" filterable>
|
||||
<el-option v-for="item of $d.Common_File_BusinessScenario" :key="item.id" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item :label="$t('dictionary:attachment:label:file')">
|
||||
<div class="upload-container">
|
||||
<el-upload class="upload-demo" action accept="" :before-upload="beforeUpload" :http-request="handleUploadFile"
|
||||
:on-preview="handlePreview" :on-remove="handleRemoveFile" :show-file-list="true" :file-list="fileList"
|
||||
:limit="1" :on-exceed="handleExceed" :disabled="(!form.FileTypeEnum && form.FileTypeEnum !== 0)">
|
||||
<el-button size="small" type="primary" :disabled="(!form.FileTypeEnum && form.FileTypeEnum !== 0)"
|
||||
:loading="btnLoading">Select</el-button>
|
||||
<!-- <span slot="tip" style="margin-left: 10px" class="el-upload__tip">
|
||||
(must be in xlsx/xls/doc/docx format)
|
||||
</span> -->
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:attachment:label:name')" prop="Name">
|
||||
<el-input v-model="form.Name" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:attachment:export:form:nameCN')" prop="NameCN">
|
||||
<el-input v-model="form.NameCN" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Id !== ''" :label="$t('dictionary:attachment:label:isDeleted')">
|
||||
<el-radio-group v-model="form.IsDeleted">
|
||||
<el-radio v-for="item of $d.YesOrNo" :label="item.value" :key="item.id">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:attachment:label:description')">
|
||||
<el-input v-model="form.Description" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" />
|
||||
</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.FileTypeEnum && form.FileTypeEnum !== 0)"
|
||||
:loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save') }}</el-button>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
addOrUpdateCommonDocument,
|
||||
uploadCommonDoc,
|
||||
Upload,
|
||||
} from '@/api/dictionary'
|
||||
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
|
||||
export default {
|
||||
name: 'TemplateForm',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
Id: '',
|
||||
Code: '',
|
||||
FileTypeEnum: 0,
|
||||
BusinessScenarioEnum: null,
|
||||
Name: '',
|
||||
NameCN: '',
|
||||
Path: '',
|
||||
Description: '',
|
||||
IsDeleted: false,
|
||||
},
|
||||
rules: {
|
||||
Code: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
|
||||
],
|
||||
Name: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
|
||||
],
|
||||
NameCN: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
|
||||
],
|
||||
BusinessScenarioEnum: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
|
||||
],
|
||||
},
|
||||
fileList: [],
|
||||
btnLoading: false,
|
||||
saveBtnLoading: false,
|
||||
loading: false,
|
||||
dictionaryList: {},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
},
|
||||
methods: {
|
||||
async initForm() {
|
||||
await this.getDicData()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
if (this.data.Path) {
|
||||
this.fileList = [
|
||||
{
|
||||
name: this.data.Name,
|
||||
path: this.data.Path,
|
||||
url: this.data.Path,
|
||||
type: this.data.Type,
|
||||
},
|
||||
]
|
||||
}
|
||||
for (const k in this.form) {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
// 获取文件类型下拉框
|
||||
getDicData() {
|
||||
this.loading = true
|
||||
getBasicDataSelects(['Common_File_ModuleType', 'Common_File_Type'])
|
||||
.then((res) => {
|
||||
this.dictionaryList = { ...res.Result }
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
beforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
this.fileList = []
|
||||
return true
|
||||
} else {
|
||||
this.$alert(this.$t('dictionary:attachment:export:alert:formatFile'))
|
||||
|
||||
return false
|
||||
}
|
||||
},
|
||||
async handleUploadFile(param) {
|
||||
this.loading = true
|
||||
this.form.FileName = param.file.name
|
||||
let extendName = param.file.name
|
||||
.substring(param.file.name.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()
|
||||
let file = await this.fileToBlob(param.file)
|
||||
let res = await this.OSSclient.put(`/System/Tools/${this.$guid()}${extendName}`, file)
|
||||
this.form.Path = this.$getObjectName(res.url)
|
||||
this.form.NameCN = param.file.name
|
||||
this.fileList.push({
|
||||
name: param.file.name,
|
||||
path: this.form.Path,
|
||||
fullPath: this.form.Path,
|
||||
url: this.form.Path,
|
||||
})
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
// Upload(formData, 1).then((res) => {
|
||||
// this.fileList.push({
|
||||
// name: param.file.name,
|
||||
// path: res.Result.FilePath,
|
||||
// fullPath: res.Result.FullFilePath,
|
||||
// url: res.Result.FilePath,
|
||||
// })
|
||||
|
||||
// })
|
||||
},
|
||||
fileToBlob(file) {
|
||||
// 创建 FileReader 对象
|
||||
const reader = new FileReader()
|
||||
return new Promise((resolve) => {
|
||||
// FileReader 添加 load 事件
|
||||
reader.addEventListener('load', (e) => {
|
||||
let blob
|
||||
if (typeof e.target.result === 'object') {
|
||||
blob = new Blob([e.target.result])
|
||||
} else {
|
||||
blob = e.target.result
|
||||
}
|
||||
resolve(blob)
|
||||
})
|
||||
// FileReader 以 ArrayBuffer 格式 读取 File 对象中数据
|
||||
reader.readAsArrayBuffer(file)
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs.sysTemplateFrom.validate((valid) => {
|
||||
if (!valid) return
|
||||
if (!this.form.Name) {
|
||||
this.$alert(this.$t('dictionary:attachment:message:msg1'))
|
||||
return
|
||||
}
|
||||
this.saveBtnLoading = true
|
||||
addOrUpdateCommonDocument(this.form)
|
||||
.then((res) => {
|
||||
this.saveBtnLoading = false
|
||||
this.$emit('closeDialog')
|
||||
this.$emit('getList')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.saveBtnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleRemoveFile() {
|
||||
this.fileList = []
|
||||
this.form.Path = ''
|
||||
this.form.NameCN = ''
|
||||
this.form.Name = ''
|
||||
},
|
||||
handlePreview(file) {
|
||||
if (file.fullPath) {
|
||||
window.open(file.fullPath, '_blank')
|
||||
}
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$message.warning(this.$t('upload:rule:maxFile1'))
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
return true
|
||||
var typeArr = ['xls', 'xlsx', 'doc', 'docx']
|
||||
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>
|
||||
@@ -0,0 +1,238 @@
|
||||
<template>
|
||||
<BaseContainer>
|
||||
<template slot="search-container">
|
||||
<el-form :inline="true" size="small">
|
||||
<!-- 业务场景 -->
|
||||
<el-form-item :label="$t('dictionary:attachment:label:businessScenario')">
|
||||
<el-select v-model="searchData.BusinessScenarioEnum" style="width: 150px">
|
||||
<el-option v-for="item of $d.Common_File_BusinessScenario" :key="item.value" :label="item.label"
|
||||
:value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 文件名称 -->
|
||||
<el-form-item :label="$t('dictionary:attachment:label:name')">
|
||||
<el-input v-model="searchData.Name" style="width: 130px" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
<!-- 查询 -->
|
||||
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-button type="primary" style="float: right" size="small" @click="handleAdd">
|
||||
{{ $t('common:button:new') }}
|
||||
</el-button>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="loading" :data="list" stripe height="100"
|
||||
@sort-change="handleSortChange">
|
||||
<el-table-column type="index" width="40" />
|
||||
<el-table-column prop="Code" :label="$t('dictionary:attachment:label:code')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<!-- 业务场景 -->
|
||||
<el-table-column prop="BusinessScenarioEnum" :label="$t('dictionary:attachment:label:businessScenario')"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
{{
|
||||
$fd(
|
||||
'Common_File_BusinessScenario',
|
||||
scope.row.BusinessScenarioEnum
|
||||
)
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column prop="Name" :label="$t('dictionary:attachment:label:name')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column prop="NameCN" :label="$t('dictionary:attachment:upload:table:nameCN')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<!-- 描述 -->
|
||||
<el-table-column prop="Description" :label="$t('dictionary:attachment:label:description')"
|
||||
show-overflow-tooltip />
|
||||
<!-- 是否废除 -->
|
||||
<el-table-column prop="IsDeleted" :label="$t('dictionary:attachment:label:isDeleted')" show-overflow-tooltip
|
||||
sortable="custom">
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
|
||||
$fd('YesOrNo', scope.row.IsDeleted)
|
||||
}}</el-tag>
|
||||
<el-tag v-else type="primary">{{
|
||||
$fd('YesOrNo', scope.row.IsDeleted)
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 上传时间 -->
|
||||
<el-table-column prop="UpdateTime" :label="$t('dictionary:attachment:label:updateTime')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
|
||||
<el-table-column :label="$t('common:action:action')" width="300">
|
||||
<template slot-scope="scope">
|
||||
<!-- <el-button type="text" @click="PreviewFile(scope.row)">
|
||||
{{ $t('common:button:preview') }}
|
||||
</el-button> -->
|
||||
<el-button type="text" @click="handleDownload(scope.row)">
|
||||
{{ $t('common:button:download') }}
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleEdit(scope.row)">
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页组件 -->
|
||||
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||
@pagination="getList" />
|
||||
|
||||
<!-- 新增/编辑 -->
|
||||
<el-dialog v-if="editDialog.visible" :visible.sync="editDialog.visible" :close-on-click-modal="false"
|
||||
:title="editDialog.title" width="600px" custom-class="base-dialog-wrapper">
|
||||
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getCommonDocumentList,
|
||||
DownloadCommonDoc,
|
||||
deleteCommonDocument,
|
||||
} from '@/api/dictionary'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import TemplateForm from './TemplateForm'
|
||||
import { downLoadFile } from '@/utils/stream.js'
|
||||
const FileTypeEnum = 0
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
FileTypeEnum: FileTypeEnum,
|
||||
BusinessScenarioEnum: null,
|
||||
Name: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'ToolsTemplate',
|
||||
components: { BaseContainer, Pagination, TemplateForm },
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
list: [],
|
||||
total: 0,
|
||||
currentRow: {},
|
||||
editDialog: { title: '', visible: false },
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
},
|
||||
computed: {
|
||||
isEN() {
|
||||
return this.$i18n.locale !== 'zh'
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
handleDelete(row) {
|
||||
// 确定删除该模版?
|
||||
this.$confirm(this.$t('dictionary:attachment:message:msg1')).then(() => {
|
||||
deleteCommonDocument(row.Id).then(() => {
|
||||
this.$message.success(this.$t('common:message:deletedSuccessfully'))
|
||||
this.getList()
|
||||
})
|
||||
}).catch(() => { })
|
||||
},
|
||||
PreviewFile(row) {
|
||||
let basePath = window.location.origin
|
||||
if (window.location.protocol !== 'https:') {
|
||||
basePath = 'https://irc.test.extimaging.com'
|
||||
}
|
||||
let data = {
|
||||
name: row.NameCN,
|
||||
path: basePath + row.Path,
|
||||
}
|
||||
this.$emit('PreviewFile', data)
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
getCommonDocumentList(this.searchData)
|
||||
.then((res) => {
|
||||
this.loading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 新增
|
||||
handleAdd() {
|
||||
this.editDialog.title = this.$t('common:button:new')
|
||||
this.currentRow = { FileTypeEnum: FileTypeEnum }
|
||||
this.editDialog.visible = true
|
||||
},
|
||||
// 下载
|
||||
async handleDownload(row) {
|
||||
try {
|
||||
this.loading = true
|
||||
let fileName = this.isEN ? row.Name : row.NameCN;
|
||||
let type = fileName
|
||||
.substring(fileName.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()
|
||||
if (!type) {
|
||||
let extendName = row.Path
|
||||
.substring(row.Path.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()
|
||||
fileName += extendName
|
||||
}
|
||||
let res = await downLoadFile(this.OSSclientConfig.basePath + row.Path, fileName)
|
||||
this.loading = false
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
// 编辑
|
||||
handleEdit(row) {
|
||||
this.editDialog.title = this.$t('common:button:edit')
|
||||
this.currentRow = { ...row }
|
||||
this.editDialog.visible = true
|
||||
},
|
||||
handleSearch() {
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
closeDialog() {
|
||||
this.editDialog.visible = false
|
||||
},
|
||||
// 排序
|
||||
handleSortChange(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>
|
||||
::v-deep .search {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
@@ -1,52 +1,22 @@
|
||||
<template>
|
||||
<div class="attachment-wrapper">
|
||||
<el-tabs v-model="activeTab" @tab-click="clickTab">
|
||||
<el-tab-pane
|
||||
v-for="item in $d.Common_File_Type"
|
||||
:key="item.value"
|
||||
:label="item.label"
|
||||
:name="String(item.value)"
|
||||
>
|
||||
<UploadTemplate
|
||||
v-if="activeTab === '1' && item.value == activeTab"
|
||||
@PreviewFile="PreviewFile"
|
||||
/>
|
||||
<ExportTemplate
|
||||
v-if="activeTab === '2' && item.value == activeTab"
|
||||
@PreviewFile="PreviewFile"
|
||||
/>
|
||||
<el-tab-pane v-for="item in $d.Common_File_Type" :key="item.value" :label="item.label" :name="String(item.value)">
|
||||
<UploadTemplate v-if="activeTab === '1' && item.value == activeTab" @PreviewFile="PreviewFile" />
|
||||
<ExportTemplate v-if="activeTab === '2' && item.value == activeTab" @PreviewFile="PreviewFile" />
|
||||
<EmailTemplate v-if="activeTab === '3' && item.value == activeTab" />
|
||||
<CommonTemplate v-if="activeTab === '4' && item.value == activeTab" />
|
||||
<SignatureTemplate
|
||||
v-if="activeTab === '5' && item.value == activeTab"
|
||||
/>
|
||||
<SignatureTemplate v-if="activeTab === '5' && item.value == activeTab" />
|
||||
<ToolsTemplate v-if="activeTab === '0' && item.value == activeTab" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<!-- 预览 -->
|
||||
<el-dialog
|
||||
v-if="Preview.visible"
|
||||
:visible.sync="Preview.visible"
|
||||
:close-on-click-modal="false"
|
||||
:fullscreen="true"
|
||||
:title="Preview.title"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<vue-office-docx
|
||||
v-if="docxTypes.includes(Preview.type)"
|
||||
:src="Preview.path"
|
||||
style="height: calc(100vh - 70px)"
|
||||
@rendered="renderedHandler"
|
||||
@error="errorHandler"
|
||||
/>
|
||||
<vue-office-excel
|
||||
v-else-if="excelTypes.includes(Preview.type)"
|
||||
:src="Preview.path"
|
||||
:options="options"
|
||||
style="height: calc(100vh - 70px)"
|
||||
@rendered="renderedHandler"
|
||||
@error="errorHandler"
|
||||
/>
|
||||
<el-dialog v-if="Preview.visible" :visible.sync="Preview.visible" :close-on-click-modal="false" :fullscreen="true"
|
||||
:title="Preview.title" width="600px" custom-class="base-dialog-wrapper">
|
||||
<vue-office-docx v-if="docxTypes.includes(Preview.type)" :src="Preview.path" style="height: calc(100vh - 70px)"
|
||||
@rendered="renderedHandler" @error="errorHandler" />
|
||||
<vue-office-excel v-else-if="excelTypes.includes(Preview.type)" :src="Preview.path" :options="options"
|
||||
style="height: calc(100vh - 70px)" @rendered="renderedHandler" @error="errorHandler" />
|
||||
<PreviewFile v-else :file-path="Preview.path" :file-type="Preview.type" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
@@ -57,6 +27,7 @@ import ExportTemplate from './components/ExportTemplate'
|
||||
import EmailTemplate from './components/EmailTemplate'
|
||||
import CommonTemplate from './components/CommonTemplate'
|
||||
import SignatureTemplate from './components/SignatureTemplate'
|
||||
import ToolsTemplate from './components/ToolsTemplate'
|
||||
import VueOfficeDocx from '@vue-office/docx'
|
||||
import '@vue-office/docx/lib/index.css'
|
||||
import VueOfficeExcel from '@vue-office/excel'
|
||||
@@ -73,6 +44,7 @@ export default {
|
||||
VueOfficeDocx,
|
||||
VueOfficeExcel,
|
||||
PreviewFile,
|
||||
ToolsTemplate
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -142,16 +114,18 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.el-tabs__header {
|
||||
height: 40px;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.el-tabs__content {
|
||||
flex: 1;
|
||||
|
||||
.el-tab-pane {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table-column type="index" width="60" />
|
||||
<!-- Group -->
|
||||
@@ -50,6 +51,7 @@
|
||||
prop="Group"
|
||||
:label="$t('template:anonymization:label:group')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Element -->
|
||||
<el-table-column
|
||||
@@ -57,24 +59,28 @@
|
||||
:label="$t('template:anonymization:label:element')"
|
||||
show-overflow-tooltip
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Tag Description -->
|
||||
<el-table-column
|
||||
prop="TagDescription"
|
||||
:label="$t('template:anonymization:label:tagDescription')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Tag DescriptionCN -->
|
||||
<el-table-column
|
||||
prop="TagDescriptionCN"
|
||||
:label="$t('template:anonymization:label:tagDescriptionCN')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Value Representation -->
|
||||
<el-table-column
|
||||
prop="ValueRepresentation"
|
||||
:label="$t('template:anonymization:label:valueRepresentation')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Is Fixed -->
|
||||
<el-table-column :label="$t('template:anonymization:label:isFixed')" width="100">
|
||||
@@ -92,6 +98,7 @@
|
||||
prop="ReplaceValue"
|
||||
:label="$t('template:anonymization:label:valueReplace')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Is Enable -->
|
||||
<el-table-column :label="$t('template:anonymization:label:isEnable')" width="100" fixed="right">
|
||||
@@ -139,7 +146,9 @@ const searchDataDefault = () => {
|
||||
IsAdd: false,
|
||||
TagDescriptionCN: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 500
|
||||
PageSize: 500,
|
||||
Asc: false,
|
||||
SortField: ''
|
||||
}
|
||||
}
|
||||
export default {
|
||||
@@ -159,6 +168,17 @@ export default {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 排序
|
||||
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()
|
||||
},
|
||||
switchChange(event, item) {
|
||||
this.loading = true
|
||||
addOrUpdateSystemAnonymization(item).then(res => {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -43,6 +43,7 @@
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<el-table-column type="index" width="60" />
|
||||
<!-- Group -->
|
||||
@@ -50,6 +51,7 @@
|
||||
prop="Group"
|
||||
:label="$t('template:anonymization:label:group')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Element -->
|
||||
<el-table-column
|
||||
@@ -57,24 +59,28 @@
|
||||
:label="$t('template:anonymization:label:element')"
|
||||
show-overflow-tooltip
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Tag Description -->
|
||||
<el-table-column
|
||||
prop="TagDescription"
|
||||
:label="$t('template:anonymization:label:tagDescription')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Tag DescriptionCN -->
|
||||
<el-table-column
|
||||
prop="TagDescriptionCN"
|
||||
:label="$t('template:anonymization:label:tagDescriptionCN')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Value Representation -->
|
||||
<el-table-column
|
||||
prop="ValueRepresentation"
|
||||
:label="$t('template:anonymization:label:valueRepresentation')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Is Fixed -->
|
||||
<el-table-column :label="$t('template:anonymization:label:isFixed')" width="100">
|
||||
@@ -92,6 +98,7 @@
|
||||
prop="ReplaceValue"
|
||||
:label="$t('template:anonymization:label:valueReplace')"
|
||||
min-width="110"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- Is Enable -->
|
||||
<el-table-column :label="$t('template:anonymization:label:isEnable')" width="100" fixed="right">
|
||||
@@ -138,7 +145,9 @@ const searchDataDefault = () => {
|
||||
TagDescriptionCN: '',
|
||||
IsAdd: true,
|
||||
PageIndex: 1,
|
||||
PageSize: 500
|
||||
PageSize: 500,
|
||||
Asc: false,
|
||||
SortField: ''
|
||||
}
|
||||
}
|
||||
export default {
|
||||
@@ -158,6 +167,17 @@ export default {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 排序
|
||||
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()
|
||||
},
|
||||
switchChange(event, item) {
|
||||
this.loading = true
|
||||
addOrUpdateSystemAnonymization(item).then(res => {
|
||||
|
||||
@@ -30,13 +30,13 @@
|
||||
<el-form-item
|
||||
:label="$t('trials:auditRecord:table:criterion')"
|
||||
>
|
||||
<el-select v-model="searchData.CriterionTypeEnum">
|
||||
<el-select v-model="searchData.CriterionTypeEnum" clearable>
|
||||
<el-option v-for="item of $d.CriterionType" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 是否通用 -->
|
||||
<el-form-item :label="$t('dictionary:medicalAudit:label:IsGeneral')">
|
||||
<el-select v-model="searchData.IsGeneral">
|
||||
<el-select v-model="searchData.IsGeneral" clearable>
|
||||
<el-option v-for="item of $d.YesOrNo" :key="item.id" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -51,6 +51,9 @@
|
||||
>
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
<el-button type="primary" @click="handleExport">
|
||||
{{ $t('common:button:export') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<span style="margin-left:auto">
|
||||
@@ -66,6 +69,7 @@
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@sort-change="handleSortByColumn"
|
||||
>
|
||||
<!-- 序号 -->
|
||||
<el-table-column
|
||||
@@ -79,6 +83,7 @@
|
||||
:label="$t('trials:MIMqcCfg:table:questionName')"
|
||||
show-overflow-tooltip
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 审核问题 -->
|
||||
<el-table-column
|
||||
@@ -86,6 +91,7 @@
|
||||
:label="$t('common:title:languageType')"
|
||||
show-overflow-tooltip
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('LanguageType', scope.row.LanguageType) }}
|
||||
@@ -97,6 +103,7 @@
|
||||
:label="$t('trials:qcCfg:table:type')"
|
||||
show-overflow-tooltip
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('QcType', scope.row.Type) }}
|
||||
@@ -108,6 +115,7 @@
|
||||
:label="$t('trials:qcCfg:table:typeValue')"
|
||||
show-overflow-tooltip
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 任务类型 -->
|
||||
<el-table-column
|
||||
@@ -115,6 +123,7 @@
|
||||
:label="$t('trials:medicalFeedbackCfg:title:taskType')"
|
||||
show-overflow-tooltip
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.ReadingCategory === 1" type="primary">
|
||||
@@ -136,6 +145,7 @@
|
||||
:label="$t('trials:auditRecord:table:criterion')"
|
||||
min-width="160"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
@@ -148,6 +158,7 @@
|
||||
:label="$t('dictionary:medicalAudit:label:IsGeneral')"
|
||||
min-width="120"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
@@ -161,6 +172,7 @@
|
||||
:label="$t('trials:qcCfg:table:parentQs')"
|
||||
show-overflow-tooltip
|
||||
min-width="140"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 父问题触发值 -->
|
||||
<el-table-column
|
||||
@@ -168,12 +180,14 @@
|
||||
:label="$t('trials:qcCfg:table:parentTriggerValue')"
|
||||
show-overflow-tooltip
|
||||
min-width="160"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!-- 是否必填 -->
|
||||
<el-table-column
|
||||
prop="IsRequired"
|
||||
:label="$t('trials:qcCfg:table:isRequired')"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsRequired) }}
|
||||
@@ -184,6 +198,7 @@
|
||||
prop="IsEnable"
|
||||
:label="$t('trials:qcCfg:table:isEnable')"
|
||||
min-width="120"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('YesOrNo', scope.row.IsEnable) }}
|
||||
@@ -215,7 +230,7 @@
|
||||
</template>
|
||||
<script>
|
||||
import { getReadingMedicineSystemQuestionList, deleteReadingMedicineSystemQuestion } from '@/api/dictionary'
|
||||
|
||||
import { GetReadingMedicineSystemQuestionList_Export } from '@/api/export'
|
||||
import BoxContent from '@/components/BoxContent'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import MedicalAuditForm from './MedicalAuditForm'
|
||||
@@ -228,7 +243,9 @@ const searchDataDefault = () => {
|
||||
LanguageType: null,
|
||||
Type: '',
|
||||
CriterionTypeEnum: null,
|
||||
IsGeneral: null
|
||||
IsGeneral: null,
|
||||
Asc: false,
|
||||
SortField: ''
|
||||
}
|
||||
}
|
||||
export default {
|
||||
@@ -248,6 +265,20 @@ export default {
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
async handleExport() {
|
||||
await GetReadingMedicineSystemQuestionList_Export(this.searchData)
|
||||
},
|
||||
// 排序
|
||||
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()
|
||||
},
|
||||
// 获取受试者列表信息
|
||||
getList() {
|
||||
this.loading = true
|
||||
|
||||
@@ -1,155 +1,86 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="tableQsForm"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
size="small"
|
||||
:disabled="type === 'look'"
|
||||
:rules="rules"
|
||||
label-width="130px"
|
||||
>
|
||||
<el-form ref="tableQsForm" v-loading="loading" :model="form" size="small" :disabled="type === 'look'" :rules="rules"
|
||||
label-width="130px">
|
||||
<div class="base-dialog-body" style="height: 550px; display:flex;flex-direction: column;">
|
||||
<div style="height: 150px;">
|
||||
<!-- 类型 -->
|
||||
<el-form-item :label="$t('trials:readingUnit:qsList:title:type')" prop="Type">
|
||||
<el-select
|
||||
v-model="form.Type"
|
||||
@change="((val)=>{qsTypeChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.Criterion_Question_Type"
|
||||
<el-select v-model="form.Type" @change="((val) => { qsTypeChange(val, form) })">
|
||||
<el-option v-for="item of $d.Criterion_Question_Type"
|
||||
v-show="item.value !== 'class' && item.value !== 'group' && item.value !== 'table' && item.value !== 'basicTable'"
|
||||
:key="item.value"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
:key="item.value" :value="item.value" :label="item.label" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 问题名称 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
prop="QuestionName"
|
||||
:rules="[
|
||||
<el-form-item v-if="form.Type !== 'group'" :label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
prop="QuestionName" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
|
||||
{ max: form.Type === 'summary' ? 300 : 100, message: `${this.$t('common:ruleMessage:maxLength')} ${form.Type === 'summary' ? 300 : 100}` }
|
||||
]"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.QuestionName"
|
||||
/>
|
||||
]">
|
||||
<el-input v-model="form.QuestionName" />
|
||||
</el-form-item>
|
||||
<!-- 问题名称(EN) -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group'"
|
||||
:label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
prop="QuestionEnName"
|
||||
:rules="[
|
||||
<el-form-item v-if="form.Type !== 'group'" :label="$t('trials:readingUnit:qsList:title:qsNameEn')"
|
||||
prop="QuestionEnName" :rules="[
|
||||
{ max: form.Type === 'summary' ? 300 : 100, message: `${this.$t('common:ruleMessage:maxLength')} ${form.Type === 'summary' ? 300 : 100}` }
|
||||
]"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.QuestionEnName"
|
||||
/>
|
||||
]">
|
||||
<el-input v-model="form.QuestionEnName" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div style="flex: 1;overflow-y:auto;">
|
||||
<!-- 公有属性 -->
|
||||
<el-divider content-position="left">{{$t('trials:readingUnit:title:publicProperties')}}</el-divider>
|
||||
<el-divider content-position="left">{{ $t('trials:readingUnit:title:publicProperties') }}</el-divider>
|
||||
<!-- 是否显示 -->
|
||||
<el-form-item v-if="form.Type !== 'group'" :label="$t('trials:readingUnit:qsList:title:isShow')" prop="ShowQuestion">
|
||||
<el-radio-group
|
||||
v-model="form.ShowQuestion"
|
||||
@change="((val)=>{isShowQuestionChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ShowQuestion"
|
||||
:key="`ShowQuestion${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
<el-form-item v-if="form.Type !== 'group'" :label="$t('trials:readingUnit:qsList:title:isShow')"
|
||||
prop="ShowQuestion">
|
||||
<el-radio-group v-model="form.ShowQuestion" @change="((val) => { isShowQuestionChange(val, form) })">
|
||||
<el-radio v-for="item of $d.ShowQuestion" :key="`ShowQuestion${item.value}`" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 显示时依赖父问题 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.ShowQuestion===1"
|
||||
:label="$t('trials:readingUnit:qsList:title:parentId')"
|
||||
prop="ParentId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.ParentId"
|
||||
clearable
|
||||
@change="((val)=>{parentQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`ParentId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
<el-form-item v-if="form.Type !== 'group' && form.ShowQuestion === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:parentId')" prop="ParentId">
|
||||
<el-select v-model="form.ParentId" clearable @change="((val) => { parentQuestionChange(val, form) })">
|
||||
<el-option v-for="item of parentOptions" :key="`ParentId${item.QuestionId}`" :label="item.QuestionName"
|
||||
:value="item.QuestionId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 显示时依赖父问题触发值 -->
|
||||
<el-form-item v-if="form.ParentId && form.ShowQuestion===1" :label="$t('trials:readingUnit:qsList:title:parentTriggerValueList')" prop="ParentTriggerValueList">
|
||||
<el-form-item v-if="form.ParentId && form.ShowQuestion === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:parentTriggerValueList')" prop="ParentTriggerValueList">
|
||||
<el-select v-model="form.ParentTriggerValueList" clearable multiple>
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="String(item.value)"
|
||||
/>
|
||||
<el-option v-for="item of parentTriggerValOptions" :key="item.id" :label="item.label"
|
||||
:value="String(item.value)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 是否必填 -->
|
||||
<el-form-item v-if="form.Type !== 'group' && form.Type !== 'table' && form.Type !== 'basicTable' && form.Type !== 'summary'" :label="$t('trials:readingUnit:qsList:title:isRequired')" prop="IsRequired">
|
||||
<el-radio-group
|
||||
v-model="form.IsRequired"
|
||||
:disabled="form.IsJudgeQuestion===true || form.ShowQuestion===2"
|
||||
@change="((val)=>{isRequiredChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.QuestionRequired"
|
||||
:key="`QuestionRequired${item.value}`"
|
||||
:label="item.value"
|
||||
>
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.Type !== 'table' && form.Type !== 'basicTable' && form.Type !== 'summary'"
|
||||
:label="$t('trials:readingUnit:qsList:title:isRequired')" prop="IsRequired">
|
||||
<el-radio-group v-model="form.IsRequired" :disabled="form.IsJudgeQuestion === true || form.ShowQuestion === 2"
|
||||
@change="((val) => { isRequiredChange(val, form) })">
|
||||
<el-radio v-for="item of $d.QuestionRequired" :key="`QuestionRequired${item.value}`" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 必填依赖父问题 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.IsRequired === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:relevanceId')"
|
||||
prop="RelevanceId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.RelevanceId"
|
||||
clearable
|
||||
@change="((val)=>{relevanceQuestionChange(val, form)})"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`RelevanceId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
<el-form-item v-if="form.Type !== 'group' && form.IsRequired === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:relevanceId')" prop="RelevanceId">
|
||||
<el-select v-model="form.RelevanceId" clearable @change="((val) => { relevanceQuestionChange(val, form) })">
|
||||
<el-option v-for="item of parentOptions" :key="`RelevanceId${item.QuestionId}`" :label="item.QuestionName"
|
||||
:value="item.QuestionId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 必填触发值 -->
|
||||
<el-form-item
|
||||
v-if="form.RelevanceId && form.IsRequired === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:relevanceValueList')"
|
||||
prop="RelevanceValueList"
|
||||
>
|
||||
<el-form-item v-if="form.RelevanceId && form.IsRequired === 1"
|
||||
:label="$t('trials:readingUnit:qsList:title:relevanceValueList')" prop="RelevanceValueList">
|
||||
<el-select v-model="form.RelevanceValueList" clearable multiple>
|
||||
<el-option
|
||||
v-for="item of reParentTriggerValOptions"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="String(item.value)"
|
||||
/>
|
||||
<el-option v-for="item of reParentTriggerValOptions" :key="item.id" :label="item.label"
|
||||
:value="String(item.value)" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 导出标识 -->
|
||||
@@ -174,175 +105,106 @@
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
<!-- 导出结果 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:qsList:title:ExportResult')"
|
||||
v-if="form.Type === 'radio' || form.Type === 'select' || form.Type === 'input' || form.Type === 'textarea' || form.Type === 'number' || form.Type === 'class' || form.Type === 'calculation'"
|
||||
>
|
||||
<el-form-item :label="$t('trials:readingUnit:qsList:title:ExportResult')"
|
||||
v-if="form.Type === 'radio' || form.Type === 'select' || form.Type === 'input' || form.Type === 'textarea' || form.Type === 'number' || form.Type === 'class' || form.Type === 'calculation'">
|
||||
<el-select v-model="form.ExportResult" multiple>
|
||||
<el-option
|
||||
v-for="item in CriterionDictionaryList.ExportResult"
|
||||
:key="`ExportResult${item.value}`"
|
||||
:value="parseInt(item.Code)"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value"
|
||||
>
|
||||
<el-option v-for="item in CriterionDictionaryList.ExportResult" :key="`ExportResult${item.value}`"
|
||||
:value="parseInt(item.Code)" :label="$i18n.locale === 'zh' ? item.ValueCN : item.Value">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 限制编辑 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:qsList:title:limitEdit')"
|
||||
v-if="form.Type !== 'summary'"
|
||||
prop="LimitEdit"
|
||||
:rules="[
|
||||
<el-form-item :label="$t('trials:readingUnit:qsList:title:limitEdit')" v-if="form.Type !== 'summary'"
|
||||
prop="LimitEdit" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
]">
|
||||
<el-radio-group v-model="form.LimitEdit">
|
||||
<el-radio v-for="item of $d.LimitEdit" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 问题标识 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.Type !== 'summary'"
|
||||
:label="$t('dictionary:template:criterionConfig:table:questionMark')"
|
||||
prop="QuestionMark"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.QuestionMark"
|
||||
clearable
|
||||
>
|
||||
<el-option
|
||||
v-for="item of CriterionDictionaryList.QuestionMark"
|
||||
:key="item.Id"
|
||||
:value="parseInt(item.Code)"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value"
|
||||
/>
|
||||
<el-form-item v-if="form.Type !== 'group' && form.Type !== 'summary'"
|
||||
:label="$t('dictionary:template:criterionConfig:table:questionMark')" prop="QuestionMark">
|
||||
<el-select v-model="form.QuestionMark" clearable>
|
||||
<el-option v-for="item of CriterionDictionaryList.QuestionMark" :key="item.Id" :value="parseInt(item.Code)"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 注释 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:qsList:title:Remark')"
|
||||
prop="Remark"
|
||||
>
|
||||
<el-form-item :label="$t('trials:readingUnit:qsList:title:Remark')" prop="Remark">
|
||||
<el-input v-model="form.Remark" />
|
||||
</el-form-item>
|
||||
<!-- 序号 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:qsList:title:order')"
|
||||
prop="ShowOrder"
|
||||
:rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="form.ShowOrder"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
/>
|
||||
<el-form-item :label="$t('trials:readingUnit:qsList:title:order')" prop="ShowOrder" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||
]">
|
||||
<el-input-number v-model="form.ShowOrder" controls-position="right" :min="0" />
|
||||
</el-form-item>
|
||||
<!-- 重复出现最大次数 -->
|
||||
<el-form-item :label="$t('dictionary:template:criterionConfig:table:maxRowCount')" v-if="form.Type !== 'summary' && form.Type !== 'screenshot' && form.Type !== 'upload'">
|
||||
<el-input-number
|
||||
v-model="form.MaxRowCount"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
:max="10"
|
||||
/>
|
||||
<el-form-item :label="$t('dictionary:template:criterionConfig:table:maxRowCount')"
|
||||
v-if="form.Type !== 'summary' && form.Type !== 'screenshot' && form.Type !== 'upload'">
|
||||
<el-input-number v-model="form.MaxRowCount" controls-position="right" :min="0" :max="10" />
|
||||
</el-form-item>
|
||||
<!-- 问题分类 -->
|
||||
<el-form-item :label="$t('dictionary:template:criterionConfig:table:questionClassify')" v-if="criterionType === 2">
|
||||
<el-form-item :label="$t('dictionary:template:criterionConfig:table:questionClassify')"
|
||||
v-if="criterionType === 2">
|
||||
<el-select v-model="form.QuestionClassify" clearable>
|
||||
<el-option
|
||||
v-for="item of $d.QuestionClassify"
|
||||
:key="item.id"
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
<el-option v-for="item of $d.QuestionClassify" :key="item.id" :label="item.label" :value="item.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 私有属性 -->
|
||||
<el-divider content-position="left">{{$t('trials:readingUnit:title:privateProperties')}}</el-divider>
|
||||
<el-divider content-position="left">{{ $t('trials:readingUnit:title:privateProperties') }}</el-divider>
|
||||
<!-- 下拉框单选或多选 -->
|
||||
<el-form-item v-if="form.Type === 'select'" :label="$t('trials:readingUnit:qsList:title:MultipleSelect')"
|
||||
prop="OptionTypeEnum" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify') }
|
||||
]">
|
||||
<el-radio-group v-model="form.OptionTypeEnum">
|
||||
<el-radio v-for="item of $d.OptionType" :key="item.id" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 选项类型 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'input'"
|
||||
:label="$t('trials:readingUnit:label:QuestionGenre')"
|
||||
prop="TableQuestionType"
|
||||
:rules="[
|
||||
{ required: form.Type !== 'input', message: this.$t('common:ruleMessage:select')}
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.TableQuestionType"
|
||||
@change="((val)=>{tableQuestionTypeChange(val, form)})"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.TableQuestionType"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
:disabled="(form.Type === 'radio' && (item.value===1 || item.value===2)) || (form.Type === 'input' && (item.value===0 || item.value===3))"
|
||||
>
|
||||
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'input'"
|
||||
:label="$t('trials:readingUnit:label:QuestionGenre')" prop="TableQuestionType" :rules="[
|
||||
{ required: form.Type !== 'input', message: this.$t('common:ruleMessage:select') }
|
||||
]">
|
||||
<el-radio-group v-model="form.TableQuestionType" @change="((val) => { tableQuestionTypeChange(val, form) })">
|
||||
<el-radio v-for="item of $d.TableQuestionType" :key="item.id" :label="item.value"
|
||||
:disabled="(form.Type === 'radio' && (item.value === 1 || item.value === 2)) || (form.Type === 'input' && (item.value === 0 || item.value === 3))">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 选项 -->
|
||||
<el-form-item
|
||||
v-if="form.TableQuestionType === 0 || form.Type === 'class'"
|
||||
:label="$t('trials:qcCfg:table:typeValue')"
|
||||
prop="TypeValue"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.TypeValue"
|
||||
:placeholder="$t('trials:qcCfg:message:typeValue')"
|
||||
@change="typeValueChange"
|
||||
/>
|
||||
<el-form-item v-if="form.TableQuestionType === 0 || form.Type === 'class'"
|
||||
:label="$t('trials:qcCfg:table:typeValue')" prop="TypeValue">
|
||||
<el-input v-model="form.TypeValue" :placeholder="$t('trials:qcCfg:message:typeValue')"
|
||||
@change="typeValueChange" />
|
||||
</el-form-item>
|
||||
<!-- 关联问题 -->
|
||||
<el-form-item
|
||||
v-if="form.TableQuestionType === 2"
|
||||
:label="$t('dictionary:template:criterionConfig:table:dependParentId')"
|
||||
prop="DependParentId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.DependParentId"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
:key="`DependParentId${item.QuestionId}`"
|
||||
:label="item.QuestionName"
|
||||
:value="item.QuestionId"
|
||||
/>
|
||||
<el-form-item v-if="form.TableQuestionType === 2"
|
||||
:label="$t('dictionary:template:criterionConfig:table:dependParentId')" prop="DependParentId">
|
||||
<el-select v-model="form.DependParentId">
|
||||
<el-option v-for="item of parentOptions" :key="`DependParentId${item.QuestionId}`"
|
||||
:label="item.QuestionName" :value="item.QuestionId" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 关联字段 -->
|
||||
<el-form-item
|
||||
v-if="form.TableQuestionType === 1 || !!form.DependParentId"
|
||||
:label="$t('dictionary:template:criterionConfig:table:dataTableColumn')"
|
||||
prop="DataTableColumn"
|
||||
>
|
||||
<el-form-item v-if="form.TableQuestionType === 1 || !!form.DependParentId"
|
||||
:label="$t('dictionary:template:criterionConfig:table:dataTableColumn')" prop="DataTableColumn">
|
||||
<el-select v-model="form.DataTableColumn">
|
||||
<el-option
|
||||
v-for="item of CriterionDictionaryList.OrganColumn"
|
||||
:key="item.Id"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value"
|
||||
:value="item.Code"
|
||||
/>
|
||||
<el-option v-for="item of CriterionDictionaryList.OrganColumn" :key="item.Id"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value" :value="item.Code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 关联字典 -->
|
||||
<el-form-item
|
||||
v-if="form.TableQuestionType === 3 || form.TableQuestionType === 2"
|
||||
:label="$t('dictionary:template:criterionConfig:table:relatedDictionaryCode')"
|
||||
prop="DictionaryCode"
|
||||
:rules="[{ required: form.TableQuestionType === 3, message: '请选择', trigger: 'blur' }]"
|
||||
>
|
||||
<el-form-item v-if="form.TableQuestionType === 3 || form.TableQuestionType === 2"
|
||||
:label="$t('dictionary:template:criterionConfig:table:relatedDictionaryCode')" prop="DictionaryCode"
|
||||
:rules="[{ required: form.TableQuestionType === 3, message: '请选择', trigger: 'blur' }]">
|
||||
<el-select v-model="form.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of dicList"
|
||||
:key="item.Id"
|
||||
:label="item.Code"
|
||||
:value="item.Code"
|
||||
/>
|
||||
<el-option v-for="item of dicList" :key="item.Id" :label="item.Code" :value="item.Code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 默认值 -->
|
||||
@@ -354,35 +216,23 @@
|
||||
:label="item.label"
|
||||
:value="item.value.toString()"
|
||||
/> -->
|
||||
<el-option
|
||||
v-for="item of highlightAnswers"
|
||||
:key="item.Id"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value"
|
||||
:value="item.Code"
|
||||
/>
|
||||
<el-option v-for="item of highlightAnswers" :key="item.Id"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value" :value="item.Code" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 默认值 -->
|
||||
<el-form-item v-if="form.TableQuestionType === 0" :label="$t('trials:readingUnit:qsList:title:defaultValue')">
|
||||
<el-select v-model="form.DefaultValue" clearable>
|
||||
<el-option
|
||||
v-for="item of form.TypeValue ? form.TypeValue.split('|') : []"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
<el-option v-for="item of form.TypeValue ? form.TypeValue.split('|') : []" :key="item" :label="item"
|
||||
:value="item" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 高亮标记值 -->
|
||||
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio'" :label="$t('trials:readingUnit:qsList:title:highlightAnswers')" prop="HighlightAnswerList">
|
||||
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio'"
|
||||
:label="$t('trials:readingUnit:qsList:title:highlightAnswers')" prop="HighlightAnswerList">
|
||||
<el-select v-model="form.HighlightAnswerList" clearable multiple>
|
||||
<template v-if="form.TypeValue">
|
||||
<el-option
|
||||
v-for="item of form.TypeValue.split('|')"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
/>
|
||||
<el-option v-for="item of form.TypeValue.split('|')" :key="item" :label="item" :value="item" />
|
||||
</template>
|
||||
<template v-else-if="form.DictionaryCode">
|
||||
<!-- <el-option
|
||||
@@ -391,24 +241,16 @@
|
||||
:label="item.label"
|
||||
:value="item.value.toString()"
|
||||
/> -->
|
||||
<el-option
|
||||
v-for="item of highlightAnswers"
|
||||
:key="item.Id"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value"
|
||||
:value="item.Code"
|
||||
/>
|
||||
<el-option v-for="item of highlightAnswers" :key="item.Id"
|
||||
:label="$i18n.locale === 'zh' ? item.ValueCN : item.Value" :value="item.Code" />
|
||||
</template>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 最大长度 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'input' || form.Type === 'textarea'"
|
||||
:label="$t('trials:readingUnit:qsList:title:MaxAnswerLength')"
|
||||
prop="MaxAnswerLength"
|
||||
:rules="[
|
||||
<el-form-item v-if="form.Type === 'input' || form.Type === 'textarea'"
|
||||
:label="$t('trials:readingUnit:qsList:title:MaxAnswerLength')" prop="MaxAnswerLength" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
]">
|
||||
<el-input-number v-model="form.MaxAnswerLength" :min="0"></el-input-number>
|
||||
</el-form-item>
|
||||
<!-- 是否复制前值 -->
|
||||
@@ -425,138 +267,82 @@
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<!-- 数值类型 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
:label="$t('trials:readingUnit:qsList:title:valueType')"
|
||||
prop="ValueType"
|
||||
:rules="[
|
||||
<el-form-item v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
:label="$t('trials:readingUnit:qsList:title:valueType')" prop="ValueType" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select') }
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ValueType"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ValueType"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
]">
|
||||
<el-radio-group v-model="form.ValueType">
|
||||
<el-radio v-for="item of $d.ValueType" :key="item.id" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
<!-- 单位 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
:label="$t('trials:readingUnit:qsList:title:unit')"
|
||||
prop="Unit"
|
||||
:rules="[
|
||||
<el-form-item v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
:label="$t('trials:readingUnit:qsList:title:unit')" prop="Unit" :rules="[
|
||||
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
|
||||
]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.Unit"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ValueUnit"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
]">
|
||||
<el-radio-group v-model="form.Unit">
|
||||
<el-radio v-for="item of $d.ValueUnit" :key="item.id" :label="item.value">
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 图表展示-->
|
||||
<el-form-item v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
:label="$t('trials:readingUnit:qsList:title:ShowChartTypeEnum')" prop="ShowChartTypeEnum">
|
||||
<el-radio-group v-model="form.ShowChartTypeEnum">
|
||||
<el-radio v-for="item of $d.ShowChartType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<!-- 最大上传个数 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'upload'"
|
||||
:label="$t('trials:readingUnit:qsList:title:imageCount')"
|
||||
prop="ImageCount"
|
||||
>
|
||||
<el-input-number
|
||||
v-model="form.ImageCount"
|
||||
controls-position="right"
|
||||
:min="0"
|
||||
:max="10"
|
||||
/>
|
||||
<el-form-item v-if="form.Type === 'upload'" :label="$t('trials:readingUnit:qsList:title:imageCount')"
|
||||
prop="ImageCount">
|
||||
<el-input-number v-model="form.ImageCount" controls-position="right" :min="0" :max="10" />
|
||||
</el-form-item>
|
||||
<!-- 文件类型 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'upload'"
|
||||
:label="$t('trials:readingUnit:qsList:title:FileType')"
|
||||
<el-form-item v-if="form.Type === 'upload'" :label="$t('trials:readingUnit:qsList:title:FileType')"
|
||||
prop="FileType"
|
||||
:rules="[{ type: 'array', required: true, message: this.$t('common:ruleMessage:specify'), trigger: [ 'change'] }]"
|
||||
>
|
||||
<el-checkbox-group
|
||||
v-model="form.FileType"
|
||||
@change="(v) => {
|
||||
if (v && v.includes('-1')) {
|
||||
form.FileType = ['-1']
|
||||
}
|
||||
}"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="item of $d.fileType"
|
||||
:key="`fileType${item.value}`"
|
||||
:value="item.value + ''"
|
||||
:label="item.value"
|
||||
:disabled="form.FileType && form.FileType.includes('-1') && item.value !== '-1'"
|
||||
>
|
||||
:rules="[{ type: 'array', required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['change'] }]">
|
||||
<el-checkbox-group v-model="form.FileType" @change="(v) => {
|
||||
if (v && v.includes('-1')) {
|
||||
form.FileType = ['-1']
|
||||
}
|
||||
}">
|
||||
<el-checkbox v-for="item of $d.fileType" :key="`fileType${item.value}`" :value="item.value + ''"
|
||||
:label="item.value" :disabled="form.FileType && form.FileType.includes('-1') && item.value !== '-1'">
|
||||
{{ item.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item>
|
||||
<!-- 分类 -->
|
||||
<!-- 分类数据来源 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'class'"
|
||||
:label="$t('dictionary:template:criterionConfig:table:classifyQuestion')"
|
||||
prop="ClassifyTableQuestionId"
|
||||
>
|
||||
<el-form-item v-if="form.Type === 'class'"
|
||||
:label="$t('dictionary:template:criterionConfig:table:classifyQuestion')" prop="ClassifyTableQuestionId">
|
||||
<el-select v-model="form.ClassifyTableQuestionId" clearable>
|
||||
<el-option v-for="item of Questions" :key="item.Id" :label="item.QuestionName"
|
||||
:value="item.Id"/>
|
||||
<el-option v-for="item of Questions" :key="item.Id" :label="item.QuestionName" :value="item.Id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 分类算法 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'class'"
|
||||
:label="$t('dictionary:template:criterionConfig:table:classifyAlgorithms')"
|
||||
prop="ClassifyAlgorithms"
|
||||
>
|
||||
<el-form-item v-if="form.Type === 'class'"
|
||||
:label="$t('dictionary:template:criterionConfig:table:classifyAlgorithms')" prop="ClassifyAlgorithms">
|
||||
<div>
|
||||
<el-table
|
||||
ref="CalculateTable"
|
||||
:data="ClassifyAlgorithmsList"
|
||||
style="margin: 10px;width: 100%"
|
||||
size="small"
|
||||
>
|
||||
<el-table ref="CalculateTable" :data="ClassifyAlgorithmsList" style="margin: 10px;width: 100%" size="small">
|
||||
<!-- 运算类型 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:readingUnit:label:label')"
|
||||
show-overflow-tooltip
|
||||
min-width="70"
|
||||
>
|
||||
<el-table-column :label="$t('trials:readingUnit:label:label')" show-overflow-tooltip min-width="70">
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.label }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 运算类型 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:readingUnit:label:gt')"
|
||||
show-overflow-tooltip
|
||||
min-width="128"
|
||||
>
|
||||
<el-table-column :label="$t('trials:readingUnit:label:gt')" show-overflow-tooltip min-width="128">
|
||||
<template slot-scope="scope">
|
||||
<el-input-number v-model="scope.row.gt"></el-input-number>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 运算类型 -->
|
||||
<el-table-column
|
||||
:label="$t('trials:readingUnit:label:lt')"
|
||||
show-overflow-tooltip
|
||||
min-width="128"
|
||||
>
|
||||
<el-table-column :label="$t('trials:readingUnit:label:lt')" show-overflow-tooltip min-width="128">
|
||||
<template slot-scope="scope">
|
||||
<el-input-number v-model="scope.row.lt"></el-input-number>
|
||||
</template>
|
||||
@@ -569,11 +355,7 @@
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="close"
|
||||
>
|
||||
<el-button size="small" type="primary" @click="close">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
@@ -666,7 +448,9 @@ export default {
|
||||
ClassifyAlgorithms: null,
|
||||
// ExportIdentification: 0,
|
||||
ExportResult: [],
|
||||
DefaultValue:null
|
||||
DefaultValue: null,
|
||||
ShowChartTypeEnum: 0,
|
||||
OptionTypeEnum: 0
|
||||
// IsEnable: true
|
||||
},
|
||||
rules: {
|
||||
@@ -677,8 +461,8 @@ export default {
|
||||
// { max: 300, message: '最大长度为 300' }],
|
||||
|
||||
TypeValue: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
|
||||
{ validator: validateTypeVal, trigger: 'blur' },
|
||||
{ max: 200, message: `${this.$t('common:ruleMessage:maxLength')} 200` }],
|
||||
{ validator: validateTypeVal, trigger: 'blur' },
|
||||
{ max: 200, message: `${this.$t('common:ruleMessage:maxLength')} 200` }],
|
||||
ShowQuestion: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }],
|
||||
IsRequired: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }],
|
||||
ParentId: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }],
|
||||
@@ -776,7 +560,7 @@ export default {
|
||||
if (this.data.hasOwnProperty(k)) {
|
||||
if (k === 'ClassifyAlgorithms' && this.data[k] !== undefined && this.data[k] !== '') {
|
||||
this.ClassifyAlgorithmsList = JSON.parse(this.data[k])
|
||||
} else if(k === 'FileType'){
|
||||
} else if (k === 'FileType') {
|
||||
this.form[k] = this.data[k].split(',')
|
||||
} else {
|
||||
this.form[k] = this.data[k]
|
||||
@@ -792,10 +576,10 @@ export default {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
// this.parentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
let dicCode = this.parentOptions[index].DictionaryCode
|
||||
let res = await getCriterionDictionary({ReadingCriterionId: this.criterionId, DictionaryCode: dicCode})
|
||||
|
||||
this.parentTriggerValOptions = res.Result[dicCode].map(i=>{
|
||||
return {id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code}
|
||||
let res = await getCriterionDictionary({ ReadingCriterionId: this.criterionId, DictionaryCode: dicCode })
|
||||
|
||||
this.parentTriggerValOptions = res.Result[dicCode].map(i => {
|
||||
return { id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code }
|
||||
})
|
||||
} else {
|
||||
const options = []
|
||||
@@ -814,9 +598,9 @@ export default {
|
||||
if (this.parentOptions[i].QuestionGenre === 3) {
|
||||
// this.reParentTriggerValOptions = this.$d[this.parentOptions[i].DictionaryCode]
|
||||
let dicCode = this.parentOptions[i].DictionaryCode
|
||||
let res = await getCriterionDictionary({ReadingCriterionId: this.criterionId, DictionaryCode: dicCode})
|
||||
this.reParentTriggerValOptions = res.Result[dicCode].map(i=>{
|
||||
return {id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code}
|
||||
let res = await getCriterionDictionary({ ReadingCriterionId: this.criterionId, DictionaryCode: dicCode })
|
||||
this.reParentTriggerValOptions = res.Result[dicCode].map(i => {
|
||||
return { id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code }
|
||||
})
|
||||
} else {
|
||||
const options = []
|
||||
@@ -903,12 +687,12 @@ export default {
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
// this.parentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
let dicCode = this.parentOptions[index].DictionaryCode
|
||||
let res = await getCriterionDictionary({ReadingCriterionId: this.criterionId, DictionaryCode: dicCode})
|
||||
|
||||
this.parentTriggerValOptions = res.Result[dicCode].map(i=>{
|
||||
return {id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code}
|
||||
})
|
||||
let dicCode = this.parentOptions[index].DictionaryCode
|
||||
let res = await getCriterionDictionary({ ReadingCriterionId: this.criterionId, DictionaryCode: dicCode })
|
||||
|
||||
this.parentTriggerValOptions = res.Result[dicCode].map(i => {
|
||||
return { id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code }
|
||||
})
|
||||
} else {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
@@ -929,10 +713,10 @@ export default {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
// this.reParentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
let dicCode = this.parentOptions[index].DictionaryCode
|
||||
let res = await getCriterionDictionary({ReadingCriterionId: this.criterionId, DictionaryCode: dicCode})
|
||||
|
||||
this.reParentTriggerValOptions = res.Result[dicCode].map(i=>{
|
||||
return {id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code}
|
||||
let res = await getCriterionDictionary({ ReadingCriterionId: this.criterionId, DictionaryCode: dicCode })
|
||||
|
||||
this.reParentTriggerValOptions = res.Result[dicCode].map(i => {
|
||||
return { id: i.Id, label: this.$i18n.locale === 'zh' ? i.ValueCN : i.Value, value: i.Code }
|
||||
})
|
||||
} else {
|
||||
const options = []
|
||||
@@ -993,6 +777,8 @@ export default {
|
||||
// form.ExportIdentification = 0
|
||||
form.ExportResult = []
|
||||
form.DefaultValue = null
|
||||
form.ShowChartTypeEnum = 0
|
||||
form.OptionTypeEnum = 0
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
@@ -1001,5 +787,4 @@ export default {
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
<style lang="scss" scoped></style>
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
</el-select>
|
||||
</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-option v-for="item of $d.YesOrNo" :value="item.value" :label="item.label" :key="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<!-- 是否启用 -->
|
||||
<el-form-item :label="$t('trials:emailManageCfg:table:IsEnable')" v-if="!systemLevel">
|
||||
<el-select v-model="searchData.IsEnable" clearable style="width: 100px">
|
||||
@@ -41,7 +41,7 @@
|
||||
<el-option v-for="item of UserTypeList" :value="item.value" :label="item.label" :key="item.id" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:emailManageCfg:form:EmailUrgent')" v-if="systemLevel === 1">
|
||||
<el-form-item :label="$t('trials:emailManageCfg:form:EmailUrgent')">
|
||||
<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>
|
||||
@@ -86,7 +86,7 @@
|
||||
:label="$t('trials:reviewTrack:table:criterionName')" show-overflow-tooltip sortable="custom" min-width="120">
|
||||
<template slot-scope="scope">
|
||||
{{scope.row.CriterionTypeList ? scope.row.CriterionTypeList.map(item => $fd('CriterionType', item)).join(', ')
|
||||
: ''}}
|
||||
: ''}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 邮件主题(中文) -->
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
<el-form-item :label="$t('dictionary:sign:label:sceneType')" prop="Name">
|
||||
<el-input v-model="form.Name" />
|
||||
</el-form-item>
|
||||
<el-form-item label="$t('dictionary:sign:label:value')" prop="Value">
|
||||
<el-form-item :label="$t('dictionary:sign:label:value')" prop="Value">
|
||||
<el-input v-model="form.Value" type="textarea" rows="5" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('dictionary:sign:label:valueCN')" prop="ValueCN">
|
||||
|
||||
@@ -164,6 +164,14 @@ export default {
|
||||
},
|
||||
},
|
||||
],
|
||||
Email: [
|
||||
{
|
||||
// type: 'email',
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: this.$t('rules:email'),
|
||||
trigger: 'blur,change',
|
||||
},
|
||||
]
|
||||
},
|
||||
userId: null,
|
||||
loading: false,
|
||||
|
||||
@@ -125,6 +125,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
|
||||
+79
-134
@@ -7,20 +7,13 @@
|
||||
<div class="login-l">
|
||||
<div class="login-logo">
|
||||
<img v-if="language === 'zh'" src="@/assets/zzlogo2.png" alt="" />
|
||||
<img
|
||||
v-else-if="NODE_ENV === 'usa'"
|
||||
src="@/assets/zzlogo-usa.png"
|
||||
alt=""
|
||||
class="usa-logo"
|
||||
/>
|
||||
<img v-else-if="NODE_ENV === 'usa'" src="@/assets/zzlogo-usa.png" alt="" class="usa-logo" />
|
||||
<img v-else src="@/assets/zzlogo4.png" alt="" />
|
||||
</div>
|
||||
<div
|
||||
:class="{
|
||||
'login-image': true,
|
||||
'login-image-usa': true,
|
||||
}"
|
||||
>
|
||||
<div :class="{
|
||||
'login-image': true,
|
||||
'login-image-usa': true,
|
||||
}">
|
||||
<svg-icon icon-class="login-bg" style="width: 90%; height: 90%" />
|
||||
<!-- <img src="@/assets/login-bg.png" v-else /> -->
|
||||
</div>
|
||||
@@ -29,77 +22,43 @@
|
||||
<div class="title-container">
|
||||
<!-- IRC Management System -->
|
||||
<div v-if="NODE_ENV === 'usa'">
|
||||
<svg-icon
|
||||
icon-class="login-logo"
|
||||
style="width: 300px; height: 94px"
|
||||
/>
|
||||
<svg-icon icon-class="login-logo" style="width: 300px; height: 94px" />
|
||||
</div>
|
||||
<div class="title" v-else>{{ $t('login:title:system') }}</div>
|
||||
</div>
|
||||
<el-form
|
||||
ref="loginForm"
|
||||
:model="loginForm"
|
||||
:rules="loginRules"
|
||||
class="login-form"
|
||||
auto-complete="on"
|
||||
label-position="left"
|
||||
>
|
||||
<el-form-item
|
||||
prop="username"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('login:formRule:userName'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<el-form ref="loginForm" :model="loginForm" :rules="loginRules" class="login-form" auto-complete="on"
|
||||
label-position="left">
|
||||
<el-form-item prop="username" :rules="[
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('login:formRule:userName'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
]">
|
||||
<span class="svg-container">
|
||||
<svg-icon icon-class="user" />
|
||||
</span>
|
||||
<!-- User Name -->
|
||||
<el-input
|
||||
ref="username"
|
||||
v-model="loginForm.username"
|
||||
size="small"
|
||||
:placeholder="$t('login:form:userName')"
|
||||
name="username"
|
||||
type="text"
|
||||
tabindex="1"
|
||||
/>
|
||||
<el-input ref="username" v-model="loginForm.username" size="small" :placeholder="$t('login:form:userName')"
|
||||
name="username" type="text" tabindex="1" />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item
|
||||
prop="password"
|
||||
:rules="[
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('login:formRule:password'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<el-form-item prop="password" :rules="[
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('login:formRule:password'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
]">
|
||||
<span class="svg-container">
|
||||
<svg-icon icon-class="password" />
|
||||
</span>
|
||||
<!-- password -->
|
||||
<el-input
|
||||
:key="passwordType"
|
||||
ref="password"
|
||||
v-model="loginForm.password"
|
||||
size="small"
|
||||
:type="passwordType"
|
||||
:placeholder="$t('login:form:password')"
|
||||
name="password"
|
||||
auto-complete="new-password"
|
||||
autocomplete="new-password"
|
||||
tabindex="2"
|
||||
@keyup.enter.native="handleLogin"
|
||||
/>
|
||||
<el-input :key="passwordType" ref="password" v-model="loginForm.password" size="small" :type="passwordType"
|
||||
:placeholder="$t('login:form:password')" name="password" auto-complete="new-password"
|
||||
autocomplete="new-password" tabindex="2" @keyup.enter.native="handleLogin" />
|
||||
<span class="show-pwd" @click="showPwd">
|
||||
<svg-icon
|
||||
:icon-class="passwordType === 'password' ? 'eye' : 'eye-open'"
|
||||
/>
|
||||
<svg-icon :icon-class="passwordType === 'password' ? 'eye' : 'eye-open'" />
|
||||
</span>
|
||||
<!-- <el-input
|
||||
:key="passwordType"
|
||||
@@ -118,33 +77,20 @@
|
||||
</span> -->
|
||||
</el-form-item>
|
||||
<!-- Login -->
|
||||
<el-button
|
||||
:loading="loading"
|
||||
type="primary"
|
||||
style="
|
||||
<el-button :loading="loading" type="primary" style="
|
||||
width: 100%;
|
||||
margin-bottom: 10px;
|
||||
background-color: rgb(0, 147, 221);
|
||||
"
|
||||
size="medium"
|
||||
@click.native.prevent="handleLogin"
|
||||
>
|
||||
" size="medium" @click.native.prevent="handleLogin">
|
||||
{{ $t('login:button:login') }}
|
||||
</el-button>
|
||||
<div style="text-align: right">
|
||||
<TopLang
|
||||
v-if="
|
||||
VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1' &&
|
||||
NODE_ENV !== 'usa'
|
||||
"
|
||||
/>
|
||||
<TopLang v-if="
|
||||
VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1' &&
|
||||
NODE_ENV !== 'usa'
|
||||
" />
|
||||
<!-- Forget password? -->
|
||||
<el-button
|
||||
type="text"
|
||||
size="medium"
|
||||
@click.native.prevent="handleResetPwd"
|
||||
style="color: rgb(0, 147, 221)"
|
||||
>
|
||||
<el-button type="text" size="medium" @click.native.prevent="handleResetPwd" style="color: rgb(0, 147, 221)">
|
||||
{{ $t('login:button:forgetPassword') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -152,19 +98,14 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="language === 'zh'" class="login-footer">
|
||||
<span
|
||||
>Copyright © {{ new Date().getFullYear() }} 上海展影医疗科技有限公司
|
||||
版权所有</span
|
||||
>
|
||||
<span>Copyright © {{ new Date().getFullYear() }} 上海展影医疗科技有限公司
|
||||
版权所有</span>
|
||||
<span> | </span>
|
||||
<a target="_blank" href="https://beian.miit.gov.cn/">
|
||||
<span> 沪ICP备2021037850-2 </span>
|
||||
</a>
|
||||
<span> | </span>
|
||||
<a
|
||||
target="_blank"
|
||||
href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31011002005859"
|
||||
>
|
||||
<a target="_blank" href="http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=31011002005859">
|
||||
<img src="@/assets/filing.png" />
|
||||
<span>沪公网安备 31011002005859号</span>
|
||||
</a>
|
||||
@@ -180,43 +121,23 @@
|
||||
<span style="color: #428bca">About</span>
|
||||
</a>
|
||||
</div>
|
||||
<Vcode
|
||||
:show="isShow"
|
||||
:fail-text="$t('login:button:failText')"
|
||||
:success-text="$t('login:button:successText')"
|
||||
:slider-text="$t('login:button:sliderText')"
|
||||
:imgs="[Img1]"
|
||||
@success="onSuccess"
|
||||
/>
|
||||
<el-dialog
|
||||
v-if="aboutVisible"
|
||||
:visible.sync="aboutVisible"
|
||||
width="680px"
|
||||
style="margin-top: 0"
|
||||
:close-on-click-modal="false"
|
||||
size="small"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
<Vcode :show="isShow" :fail-text="$t('login:button:failText')" :success-text="$t('login:button:successText')"
|
||||
:slider-text="$t('login:button:sliderText')" :imgs="[Img1]" @success="onSuccess" />
|
||||
<el-dialog v-if="aboutVisible" :visible.sync="aboutVisible" width="680px" style="margin-top: 0"
|
||||
:close-on-click-modal="false" size="small">
|
||||
<div style="
|
||||
margin: 0 auto;
|
||||
width: 600px;
|
||||
line-height: 28px;
|
||||
text-align: center;
|
||||
"
|
||||
>
|
||||
<h1
|
||||
style="text-align: center; margin-bottom: 30px"
|
||||
v-if="NODE_ENV === 'usa'"
|
||||
>
|
||||
">
|
||||
<h1 style="text-align: center; margin-bottom: 30px" v-if="NODE_ENV === 'usa'">
|
||||
About
|
||||
</h1>
|
||||
<h1 style="text-align: center; margin-bottom: 30px" v-else>关于</h1>
|
||||
<p style="margin-bottom: 0px" v-if="NODE_ENV === 'usa'">
|
||||
<!-- {{ $t('login:title:system_title_about') }} -->
|
||||
<svg-icon
|
||||
icon-class="login-logo"
|
||||
style="width: 250px; height: 71px"
|
||||
/>
|
||||
<svg-icon icon-class="login-logo" style="width: 250px; height: 71px" />
|
||||
</p>
|
||||
<p style="margin-bottom: 0px" v-else>{{ $t('login:title:system') }}</p>
|
||||
<p style="margin-bottom: 20px; margin-top: 0">
|
||||
@@ -247,13 +168,8 @@
|
||||
</div>
|
||||
</el-dialog>
|
||||
<browserTip ref="browserTip" />
|
||||
<toggleRole
|
||||
v-if="toggleRoleVisible"
|
||||
:visible.sync="toggleRoleVisible"
|
||||
:loading="toggleRoleLoading"
|
||||
@save="loginByRole"
|
||||
@cancel="cancel"
|
||||
/>
|
||||
<toggleRole v-if="toggleRoleVisible" :visible.sync="toggleRoleVisible" :loading="toggleRoleLoading"
|
||||
@save="loginByRole" @cancel="cancel" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@@ -339,7 +255,14 @@ export default {
|
||||
this.location = this.$route.query.location
|
||||
zzSessionStorage.setItem('loginType', this.loginType)
|
||||
localStorage.setItem('location', this.location)
|
||||
if (process.env.VUE_APP_OSS_CONFIG_REGION === 'oss-us-west-1') {
|
||||
// zh-CN navigator.language
|
||||
console.log(navigator.language, 'navigator.language')
|
||||
if (navigator.language !== 'zh-CN' && navigator.language !== 'zh-TW') {
|
||||
this.$i18n.locale = 'en'
|
||||
this.setLanguage('en')
|
||||
this.$updateDictionary()
|
||||
}
|
||||
else if (process.env.VUE_APP_OSS_CONFIG_REGION === 'oss-us-west-1') {
|
||||
this.$i18n.locale = 'en'
|
||||
this.setLanguage('en')
|
||||
this.$updateDictionary()
|
||||
@@ -516,7 +439,7 @@ export default {
|
||||
Array.isArray(this.$store.state.user.roles) &&
|
||||
this.$store.state.user.roles.filter((item) => item.IsUserRoleDisabled)
|
||||
.length ===
|
||||
this.$store.state.user.roles.length - 1
|
||||
this.$store.state.user.roles.length - 1
|
||||
) {
|
||||
let role = this.$store.state.user.roles.find(
|
||||
(item) => !item.IsUserRoleDisabled
|
||||
@@ -640,6 +563,7 @@ $cursor: #fff;
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
.login-r {
|
||||
.el-form-item {
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
@@ -655,23 +579,28 @@ $cursor: #fff;
|
||||
$bg: #2d3a4b;
|
||||
$dark_gray: #889aa4;
|
||||
$light_gray: #606266;
|
||||
|
||||
.login-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
background: rgb(249, 249, 249);
|
||||
|
||||
::v-deep .el-input__inner::placeholder {
|
||||
color: $dark_gray;
|
||||
}
|
||||
|
||||
.login-header {
|
||||
margin: 10px 0px 20px 10px;
|
||||
height: 3rem;
|
||||
width: 720px;
|
||||
|
||||
.login-logo {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.login-body {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
@@ -685,32 +614,39 @@ $light_gray: #606266;
|
||||
box-sizing: border-box;
|
||||
background: rgb(255, 255, 255);
|
||||
border-radius: 10px 0px 0px 10px;
|
||||
|
||||
.login-l {
|
||||
position: relative;
|
||||
float: left;
|
||||
width: 50%;
|
||||
height: 100%;
|
||||
|
||||
.login-logo {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
left: 50px;
|
||||
|
||||
img {
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.usa-logo {
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
|
||||
.login-image {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 0px;
|
||||
// transform: translateY(-50%);
|
||||
height: 100%;
|
||||
|
||||
img {
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.login-image-usa {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
@@ -718,6 +654,7 @@ $light_gray: #606266;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
}
|
||||
|
||||
.login-r {
|
||||
position: relative;
|
||||
float: left;
|
||||
@@ -735,16 +672,19 @@ $light_gray: #606266;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.title-container {
|
||||
// margin-bottom: 50px;
|
||||
text-align: center;
|
||||
margin-top: 20%;
|
||||
|
||||
.title {
|
||||
font-size: 35px;
|
||||
color: $light_gray;
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.title-logo-message {
|
||||
font-size: 26px;
|
||||
color: $light_gray;
|
||||
@@ -784,6 +724,7 @@ $light_gray: #606266;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.login-footer {
|
||||
position: absolute;
|
||||
bottom: 50px;
|
||||
@@ -797,6 +738,7 @@ $light_gray: #606266;
|
||||
align-items: center;
|
||||
// color: rgb(180, 190, 199);
|
||||
color: #909399;
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
@@ -805,13 +747,16 @@ $light_gray: #606266;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
span {
|
||||
margin: 0 2px;
|
||||
}
|
||||
|
||||
img {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
// p{
|
||||
// display: inline-block;
|
||||
// height:20px;
|
||||
|
||||
@@ -2,13 +2,8 @@
|
||||
<template>
|
||||
<div style="width: 100%; height: 100%">
|
||||
<transition name="viewer-fade">
|
||||
<div
|
||||
v-show="urlList.length > 0"
|
||||
ref="image-viewer__wrapper"
|
||||
tabindex="-1"
|
||||
class="image-viewer__wrapper"
|
||||
:style="{ 'z-index': 5 }"
|
||||
>
|
||||
<div v-show="urlList.length > 0" ref="image-viewer__wrapper" tabindex="-1" class="image-viewer__wrapper"
|
||||
:style="{ 'z-index': 5 }">
|
||||
<span class="image-viewer_desc">
|
||||
<!-- <span v-if="studyCode">NST00006</span>
|
||||
<span v-if="modality">CT</span>
|
||||
@@ -21,18 +16,12 @@
|
||||
</span>
|
||||
<!-- Arrow -->
|
||||
<template v-if="!isSingle">
|
||||
<span
|
||||
class="image-viewer__btn image-viewer__prev"
|
||||
:class="{ 'is-disabled': !infinite && isFirst }"
|
||||
@click="prev"
|
||||
>
|
||||
<span class="image-viewer__btn image-viewer__prev" :class="{ 'is-disabled': !infinite && isFirst }"
|
||||
@click="prev">
|
||||
<i class="el-icon-arrow-left" />
|
||||
</span>
|
||||
<span
|
||||
class="el-image-viewer__btn el-image-viewer__next"
|
||||
:class="{ 'is-disabled': !infinite && isLast }"
|
||||
@click="next"
|
||||
>
|
||||
<span class="el-image-viewer__btn el-image-viewer__next" :class="{ 'is-disabled': !infinite && isLast }"
|
||||
@click="next">
|
||||
<i class="el-icon-arrow-right" />
|
||||
</span>
|
||||
</template>
|
||||
@@ -44,36 +33,19 @@
|
||||
<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')"
|
||||
/>
|
||||
<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">
|
||||
<template v-for="(item, i) in urlList">
|
||||
<img
|
||||
v-if="!~item.FileType.indexOf('pdf')"
|
||||
v-show="i === index"
|
||||
:ref="`img${i}`"
|
||||
:key="item.Id"
|
||||
crossorigin="anonymous"
|
||||
:src="
|
||||
item.FileType && item.FileType.indexOf('zip') >= 0
|
||||
? zipImg
|
||||
: `${OSSclientConfig.basePath}${item.Path}`
|
||||
"
|
||||
:style="imgStyle"
|
||||
style="max-width: 100%; max-height: 100%"
|
||||
@load="handleImgLoad"
|
||||
@error="handleImgError"
|
||||
@mousedown="handleMouseDown"
|
||||
/>
|
||||
<img v-if="!~item.FileType.indexOf('pdf')" v-show="i === index" :ref="`img${i}`" :key="item.Id"
|
||||
crossorigin="anonymous" :src="item.FileType && item.FileType.indexOf('zip') >= 0
|
||||
? zipImg
|
||||
: `${OSSclientConfig.basePath}${item.Path}`
|
||||
" :style="imgStyle" style="max-width: 100%; max-height: 100%" @load="handleImgLoad"
|
||||
@error="handleImgError" @mousedown="handleMouseDown" />
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
@@ -108,11 +80,11 @@ export default {
|
||||
},
|
||||
onSwitch: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
default: () => { },
|
||||
},
|
||||
onClose: {
|
||||
type: Function,
|
||||
default: () => {},
|
||||
default: () => { },
|
||||
},
|
||||
initialIndex: {
|
||||
type: Number,
|
||||
@@ -172,7 +144,9 @@ export default {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.reset()
|
||||
this.onSwitch(val)
|
||||
if (val >= 0) {
|
||||
this.onSwitch(this.urlList[val].Id)
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -349,6 +323,7 @@ export default {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.image-viewer__btn {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
@@ -370,6 +345,7 @@ export default {
|
||||
height: 40px;
|
||||
font-size: 40px;
|
||||
}
|
||||
|
||||
.image-viewer_desc {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
@@ -387,6 +363,7 @@ export default {
|
||||
border-radius: 17px;
|
||||
// border-radius: 2%;
|
||||
}
|
||||
|
||||
.image-viewer__canvas {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
@@ -397,6 +374,7 @@ export default {
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.image-viewer__actions {
|
||||
left: 50%;
|
||||
bottom: 30px;
|
||||
@@ -408,6 +386,7 @@ export default {
|
||||
border-color: #fff;
|
||||
border-radius: 22px;
|
||||
}
|
||||
|
||||
.image-viewer__actions__inner {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -419,6 +398,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
.image-viewer__next,
|
||||
.image-viewer__prev {
|
||||
top: 50%;
|
||||
@@ -429,15 +409,18 @@ export default {
|
||||
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%;
|
||||
@@ -447,9 +430,11 @@ export default {
|
||||
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;
|
||||
}
|
||||
@@ -459,6 +444,7 @@ export default {
|
||||
transform: translate3d(0, -20px, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, 0, 0);
|
||||
opacity: 1;
|
||||
@@ -470,6 +456,7 @@ export default {
|
||||
transform: translate3d(0, 0, 0);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
100% {
|
||||
transform: translate3d(0, -20px, 0);
|
||||
opacity: 0;
|
||||
|
||||
@@ -2,56 +2,29 @@
|
||||
<div class="none-dicom_preview-wrapper">
|
||||
<div class="image-viewer-wrapper">
|
||||
<!-- 预览图像 -->
|
||||
<ImageViewer
|
||||
v-if="previewVisible"
|
||||
:on-switch="
|
||||
(index) => {
|
||||
selected(index)
|
||||
}
|
||||
"
|
||||
:initial-index="previewImage.index"
|
||||
:url-list="previewImage.imgList"
|
||||
:study-code="previewImage.studyCode"
|
||||
:body-part="previewImage.bodyPart"
|
||||
:modality="previewImage.modality"
|
||||
:zip-img="zipImg"
|
||||
/>
|
||||
<ImageViewer v-if="previewVisible" :on-switch="(index) => {
|
||||
selected(index)
|
||||
}
|
||||
" :initial-index="previewImage.index" :url-list="previewImage.imgList" :study-code="previewImage.studyCode"
|
||||
:body-part="previewImage.bodyPart" :modality="previewImage.modality" :zip-img="zipImg" />
|
||||
</div>
|
||||
<div class="thumbnail-wrapper" style="z-index: 999; background-color: #fff">
|
||||
<div class="">
|
||||
<div class="img-wrapper">
|
||||
<el-button
|
||||
icon="el-icon-d-arrow-left"
|
||||
plain
|
||||
class="left to"
|
||||
:disabled="disabledPrev"
|
||||
@click="toRight"
|
||||
/>
|
||||
<el-button icon="el-icon-d-arrow-left" plain class="left to" :disabled="disabledPrev" @click="toRight" />
|
||||
<div ref="imagesWrapper" class="images">
|
||||
<div v-if="noData" class="empty-text">
|
||||
<slot name="empty">暂无数据</slot>
|
||||
</div>
|
||||
<div v-show="!noData" class="items" :style="itemsStyle">
|
||||
<template v-for="(item, index) in previewImage.imgList">
|
||||
<div
|
||||
v-if="!~item.FileType.indexOf('pdf')"
|
||||
:key="index"
|
||||
class="item-img"
|
||||
:style="imgSize"
|
||||
:class="{
|
||||
'is-active': index === currentIndex,
|
||||
}"
|
||||
@click="selected(index)"
|
||||
>
|
||||
<img
|
||||
:title="item.FileName"
|
||||
crossorigin="anonymous"
|
||||
:src="
|
||||
item.FileType && item.FileType.indexOf('zip') >= 0
|
||||
? zipImg
|
||||
: `${OSSclientConfig.basePath}${item.Path}`
|
||||
"
|
||||
/>
|
||||
<div v-if="!~item.FileType.indexOf('pdf')" :key="index" class="item-img" :style="imgSize" :class="{
|
||||
'is-active': item.Id === currentFileId,
|
||||
}" @click="selected(item.Id)">
|
||||
<img :title="item.FileName" crossorigin="anonymous" :src="item.FileType && item.FileType.indexOf('zip') >= 0
|
||||
? zipImg
|
||||
: `${OSSclientConfig.basePath}${item.Path}`
|
||||
" />
|
||||
<p v-if="item.FileName" class="item-date">
|
||||
{{ `${index + 1}` }}
|
||||
</p>
|
||||
@@ -59,13 +32,7 @@
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
icon="el-icon-d-arrow-right"
|
||||
:disabled="disabledNext"
|
||||
plain
|
||||
class="right to"
|
||||
@click="Left"
|
||||
/>
|
||||
<el-button icon="el-icon-d-arrow-right" :disabled="disabledNext" plain class="right to" @click="Left" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -93,6 +60,10 @@ export default {
|
||||
type: Number,
|
||||
default: null,
|
||||
},
|
||||
currentFileId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
previewImage: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
@@ -167,7 +138,7 @@ export default {
|
||||
const scope = this
|
||||
window.onresize = function () {
|
||||
scope.pageSize = scope.wrapperWidth() / scope.itemWidth
|
||||
scope.selected(scope.currentIndex)
|
||||
scope.selected(scope.currentFileId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -185,7 +156,8 @@ export default {
|
||||
this.translateX = maxTrans
|
||||
}
|
||||
},
|
||||
selected(index) {
|
||||
selected(id) {
|
||||
let index = this.previewImage.imgList.findIndex(item => item.Id === id)
|
||||
const center = this.pageSize >> 1
|
||||
// 最后一页的中间位置
|
||||
const lastCenter = this.dataLength - center
|
||||
@@ -202,7 +174,7 @@ export default {
|
||||
if (this.currentIndex !== index) {
|
||||
this.currentIndex = index
|
||||
}
|
||||
this.$emit('selectedImg', index)
|
||||
this.$emit('selectedImg', id)
|
||||
},
|
||||
wrapperWidth() {
|
||||
if (this.$refs.imagesWrapper) {
|
||||
@@ -224,25 +196,30 @@ export default {
|
||||
.image-viewer-wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.thumbnail-wrapper {
|
||||
height: 130px;
|
||||
}
|
||||
|
||||
.img-content {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin: 0 20px;
|
||||
height: 120px;
|
||||
|
||||
.to {
|
||||
width: 32px;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.images::before {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
@@ -251,16 +228,15 @@ export default {
|
||||
width: 84px;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
right top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0))
|
||||
);
|
||||
background: -webkit-gradient(linear,
|
||||
left top,
|
||||
right top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0)));
|
||||
background: -o-linear-gradient(left, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
background: linear-gradient(90deg, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
}
|
||||
|
||||
.images::after {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
@@ -270,22 +246,22 @@ export default {
|
||||
width: 84px;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
right top,
|
||||
left top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0))
|
||||
);
|
||||
background: -webkit-gradient(linear,
|
||||
right top,
|
||||
left top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0)));
|
||||
background: -o-linear-gradient(right, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
background: linear-gradient(270deg, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
}
|
||||
|
||||
.images {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 2px;
|
||||
|
||||
.empty-text {
|
||||
color: rgb(158, 158, 158);
|
||||
height: 100%;
|
||||
@@ -293,6 +269,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.items {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -302,6 +279,7 @@ export default {
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
transition: transform 0.25s ease;
|
||||
|
||||
.item-img {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
@@ -309,6 +287,7 @@ export default {
|
||||
margin-right: 8px;
|
||||
border: 2px solid rgba(0, 0, 0, 0);
|
||||
cursor: pointer;
|
||||
|
||||
.item-date {
|
||||
bottom: 0px;
|
||||
position: absolute;
|
||||
@@ -319,15 +298,18 @@ export default {
|
||||
line-height: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-img:hover::after {
|
||||
// border-color: #409EFF;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.item-img::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -342,9 +324,11 @@ export default {
|
||||
transition: opacity 0.3s ease;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.is-active {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.is-active:after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -1,84 +1,59 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="img-container">
|
||||
<el-card class="box-card left">
|
||||
<div class="title">
|
||||
<div class="title" style="display: flex;align-items: center;">
|
||||
<div style="margin-right: 5px;cursor: pointer;" @click.stop="sortFile">
|
||||
<i :class="['el-icon-caret-top', Asc === false || Asc === null ? '' : 'icon_check']"
|
||||
style="display: block;margin-bottom: -5px;"></i>
|
||||
<i :class="['el-icon-caret-bottom', Asc === true || Asc === null ? '' : 'icon_check']"
|
||||
style="display: block; margin-top: -5px;"></i>
|
||||
</div>
|
||||
{{ $t('trials:none-dicom-show:fileList') }}
|
||||
</div>
|
||||
<div class="left-content">
|
||||
<!-- 检查层级 -->
|
||||
<el-collapse v-model="activeNames" @change="handleChange">
|
||||
<el-collapse-item
|
||||
v-for="(study, i) in studyList"
|
||||
:key="study.CodeView"
|
||||
:name="study.CodeView"
|
||||
><template slot="title">
|
||||
<el-collapse-item v-for="(study, i) in studyList" :key="study.CodeView" :name="study.CodeView"><template
|
||||
slot="title">
|
||||
<div class="study-desc">
|
||||
<span>{{ study.CodeView }}</span>
|
||||
<span v-if="OtherInfo.IsShowStudyName" style="margin-left: 5px">
|
||||
{{ study.StudyName }}
|
||||
</span>
|
||||
<span style="margin: 0 5px">{{ study.Modality }}</span>
|
||||
<span>{{ getBodyPart(study.BodyPart) }}</span>
|
||||
<span>{{ getBodyPart(study.BodyPart, study.BodyPartForEditOther) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 文件层级 -->
|
||||
<div
|
||||
v-if="study.NoneDicomStudyFileList.length === 0"
|
||||
class="empty-text"
|
||||
>
|
||||
<div v-if="study.NoneDicomStudyFileList.length === 0" class="empty-text">
|
||||
<slot name="empty">{{ $t('trials:audit:message:noData') }}</slot>
|
||||
</div>
|
||||
<div v-else id="imgList" style="height: 100%; overflow: hidden">
|
||||
<template v-for="(item, j) in study.NoneDicomStudyFileList">
|
||||
<div
|
||||
:id="`img${item.Id}`"
|
||||
:key="item.Id"
|
||||
:class="{
|
||||
'is-boxActive': item.Id === currentFileId,
|
||||
}"
|
||||
class="img-box"
|
||||
@click="selected(item, i, j, true)"
|
||||
>
|
||||
<div :id="`img${item.Id}`" :key="item.Id" :class="{
|
||||
'is-boxActive': item.Id === currentFileId,
|
||||
}" class="img-box" @click="selected(item, i, j, true)">
|
||||
<div class="file-image">
|
||||
<el-image
|
||||
v-if="
|
||||
[
|
||||
'image/jpeg',
|
||||
'image/jpg',
|
||||
'image/png',
|
||||
'image/bmp',
|
||||
].includes(item.FileType)
|
||||
"
|
||||
style="width: 100%; height: 100%"
|
||||
<el-image v-if="
|
||||
[
|
||||
'image/jpeg',
|
||||
'image/jpg',
|
||||
'image/png',
|
||||
'image/bmp',
|
||||
].includes(item.FileType)
|
||||
" style="width: 100%; height: 100%"
|
||||
:src="`${OSSclientConfig.basePath}${item.Path}?x-oss-process=image/resize,w_50,h_50/format,png`"
|
||||
fit="contain"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<el-image
|
||||
v-else-if="item.FileType === 'application/pdf'"
|
||||
style="width: 100%; height: 100%"
|
||||
:src="pdf"
|
||||
fit="contain"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
<el-image
|
||||
v-else-if="
|
||||
item.FileType === 'application/x-zip-compressed'
|
||||
"
|
||||
style="width: 100%; height: 100%"
|
||||
:src="zip"
|
||||
fit="contain"
|
||||
crossorigin="anonymous"
|
||||
/>
|
||||
fit="contain" crossorigin="anonymous" />
|
||||
<el-image v-else-if="item.FileType === 'application/pdf'" style="width: 100%; height: 100%"
|
||||
:src="pdf" fit="contain" crossorigin="anonymous" />
|
||||
<el-image v-else-if="
|
||||
item.FileType === 'application/x-zip-compressed'
|
||||
" style="width: 100%; height: 100%" :src="zip" fit="contain" crossorigin="anonymous" />
|
||||
</div>
|
||||
<div v-if="item.FileName.length < 15" class="img-text">
|
||||
{{ `${j + 1}. ${item.FileName}` }}
|
||||
</div>
|
||||
<el-tooltip
|
||||
v-else
|
||||
:content="item.FileName"
|
||||
placement="bottom"
|
||||
>
|
||||
<el-tooltip v-else :content="item.FileName" placement="bottom">
|
||||
<div class="img-text">
|
||||
{{ `${j + 1}. ${item.FileName}` }}
|
||||
</div>
|
||||
@@ -86,23 +61,15 @@
|
||||
<div v-if="isQcCheck" class="switchBox">
|
||||
<div class="item">
|
||||
<span>{{ $t('trials:audit:table:isReading') }}</span>
|
||||
<el-switch
|
||||
v-model="item.IsReading"
|
||||
:disabled="item.IsDeleted || isAudit"
|
||||
@change="changeReadingStatus($event, study, item)"
|
||||
:active-text="$fd('YesOrNo', true)"
|
||||
:inactive-text="$fd('YesOrNo', false)"
|
||||
/>
|
||||
<el-switch v-model="item.IsReading" :disabled="item.IsDeleted || isAudit"
|
||||
@change="changeReadingStatus($event, study, item)" :active-text="$fd('YesOrNo', true)"
|
||||
:inactive-text="$fd('YesOrNo', false)" />
|
||||
</div>
|
||||
<div class="item">
|
||||
<span>{{ $t('trials:audit:table:isDelete') }}</span>
|
||||
<el-switch
|
||||
v-model="item.IsDeleted"
|
||||
:disabled="isAudit"
|
||||
@change="changeDeleteStatus($event, study, item)"
|
||||
:active-text="$fd('YesOrNo', true)"
|
||||
:inactive-text="$fd('YesOrNo', false)"
|
||||
/>
|
||||
<el-switch v-model="item.IsDeleted" :disabled="isAudit"
|
||||
@change="changeDeleteStatus($event, study, item)" :active-text="$fd('YesOrNo', true)"
|
||||
:inactive-text="$fd('YesOrNo', false)" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -115,14 +82,9 @@
|
||||
<!-- 预览图像 -->
|
||||
<el-card class="box-card right">
|
||||
<div style="width: 100%; height: 100%" v-if="!showPDF">
|
||||
<Preview
|
||||
v-if="previewImage.imgList.length > 0"
|
||||
ref="previewImage"
|
||||
style="width: 100%"
|
||||
:preview-image="previewImage"
|
||||
:value="currentStudyFileIndex"
|
||||
@selectedImg="selectedImg"
|
||||
/>
|
||||
<Preview v-if="previewImage.imgList.length > 0" ref="previewImage" style="width: 100%"
|
||||
:preview-image="previewImage" :value="currentStudyFileIndex" @selectedImg="selectedImg"
|
||||
:currentFileId="currentFileId" />
|
||||
</div>
|
||||
<div style="width: 100%; height: 100%" v-else>
|
||||
<PreviewFile :file-path="pdfFile.path" :file-type="pdfFile.type" />
|
||||
@@ -143,6 +105,7 @@ import zip from '@/assets/zip.jpg'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import Preview from './components/preview'
|
||||
import PreviewFile from '@/components/PreviewFile'
|
||||
import FileNameSorter from "@/utils/customSort";
|
||||
// import CheckForm from './components/form'
|
||||
export default {
|
||||
name: 'Notice',
|
||||
@@ -174,7 +137,7 @@ export default {
|
||||
subjectVisitId: '',
|
||||
sudyId: '',
|
||||
loading: false,
|
||||
bp: [],
|
||||
BodyPart: {},
|
||||
OtherInfo: {},
|
||||
showPDF: false,
|
||||
pdfFile: {
|
||||
@@ -185,10 +148,11 @@ export default {
|
||||
isAudit: false,
|
||||
|
||||
activeNames: [],
|
||||
Asc: false
|
||||
}
|
||||
},
|
||||
async created() {
|
||||
this.bp = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.isQcCheck = !!this.$route.query.isQcCheck
|
||||
},
|
||||
async mounted() {
|
||||
@@ -201,8 +165,31 @@ export default {
|
||||
this.getNoneDicomList()
|
||||
// 默认选择第一个文件
|
||||
},
|
||||
computed: {
|
||||
CriterionType() {
|
||||
return this.OtherInfo.CriterionType ? this.OtherInfo.CriterionType : 0
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleChange() {},
|
||||
sortFile() {
|
||||
if (this.Asc) {
|
||||
this.Asc = false
|
||||
} else {
|
||||
this.Asc = true
|
||||
}
|
||||
console.log(this.Asc, 'this.Asc')
|
||||
this.studyList.forEach(study => {
|
||||
if (study.NoneDicomStudyFileList.length > 0) {
|
||||
study.NoneDicomStudyFileList = FileNameSorter.sortFileNames(study.NoneDicomStudyFileList, {
|
||||
direction: this.Asc ? 'asc' : 'desc',
|
||||
key: 'FileName'
|
||||
})
|
||||
}
|
||||
})
|
||||
this.previewImage.imgList = this.studyList[this.currentStudyIndex].NoneDicomStudyFileList
|
||||
this.previewImage.index = this.studyList[this.currentStudyIndex].NoneDicomStudyFileList.findIndex(item => item.Id === this.currentFileId)
|
||||
},
|
||||
handleChange() { },
|
||||
changeReadingStatus(callback, row, file) {
|
||||
let statusStr = ''
|
||||
if (callback) {
|
||||
@@ -245,7 +232,7 @@ export default {
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
.catch(() => {})
|
||||
.catch(() => { })
|
||||
},
|
||||
changeDeleteStatus(callback, row, file) {
|
||||
let statusStr = ''
|
||||
@@ -295,8 +282,8 @@ export default {
|
||||
// file.IsDeleted = !file.IsDeleted
|
||||
})
|
||||
},
|
||||
getBodyPart(bodyPart) {
|
||||
if (!bodyPart) return ''
|
||||
getBodyPart(bodyPart, other) {
|
||||
if (!bodyPart && !other) return ''
|
||||
var separator = ','
|
||||
if (bodyPart.indexOf('|') > -1) {
|
||||
separator = '|'
|
||||
@@ -307,14 +294,12 @@ export default {
|
||||
}
|
||||
var arr = bodyPart.split(separator)
|
||||
var newArr = arr.map((i) => {
|
||||
return this.$fd(
|
||||
'Bodypart',
|
||||
i.trim(),
|
||||
'Code',
|
||||
{ Bodypart: this.bp },
|
||||
'Name'
|
||||
)
|
||||
return this.$fd('Bodypart', i.trim(), 'Code', this.BodyPart, 'Name')
|
||||
})
|
||||
if (other) {
|
||||
newArr.push(other)
|
||||
}
|
||||
newArr = newArr.filter(Boolean)
|
||||
return newArr.join(' | ')
|
||||
},
|
||||
// 获取非Dicom检查信息
|
||||
@@ -325,7 +310,8 @@ export default {
|
||||
this.studyId,
|
||||
false,
|
||||
this.$route.query.visitTaskId,
|
||||
!!this.$route.query.isReading
|
||||
!!this.$route.query.isReading,
|
||||
this.$route.query.isImageSegmentLabel,
|
||||
)
|
||||
.then((res) => {
|
||||
this.studyList = res.Result
|
||||
@@ -336,11 +322,13 @@ export default {
|
||||
return item.NoneDicomStudyFileList.length > 0
|
||||
})
|
||||
this.activeNames = this.studyList.map((item) => item.CodeView)
|
||||
console.log(this.activeNames)
|
||||
if (studyIndex > -1) {
|
||||
var fileObj = this.studyList[studyIndex]['NoneDicomStudyFileList']
|
||||
this.selected(fileObj[0], studyIndex, 0, true)
|
||||
}
|
||||
if (this.CriterionType === 19 || this.CriterionType === 20) {
|
||||
this.sortFile()
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
@@ -367,12 +355,13 @@ export default {
|
||||
this.previewImage.modality = this.studyList[studyIndex].Modality
|
||||
this.$nextTick(() => {
|
||||
if (isChangeSub) {
|
||||
this.$refs['previewImage'].selected(fileIndex)
|
||||
this.$refs['previewImage'].selected(this.currentFileId)
|
||||
}
|
||||
})
|
||||
},
|
||||
selectedImg(fileIndex) {
|
||||
selectedImg(id) {
|
||||
if (this.studyList.length > 0) {
|
||||
let fileIndex = this.studyList[this.currentStudyIndex].NoneDicomStudyFileList.findIndex(item => item.Id === id)
|
||||
this.currentStudyFileIndex = fileIndex
|
||||
this.currentFileId =
|
||||
this.studyList[this.currentStudyIndex].NoneDicomStudyFileList[
|
||||
@@ -400,30 +389,39 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.icon_check {
|
||||
color: #409EFF;
|
||||
}
|
||||
|
||||
.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%;
|
||||
@@ -434,6 +432,7 @@ export default {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
@@ -443,6 +442,7 @@ export default {
|
||||
background-color: #4e4e4e;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.left-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
@@ -474,6 +474,7 @@ export default {
|
||||
// margin-bottom: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.img-text {
|
||||
display: inline-block;
|
||||
width: calc(100% - 60px);
|
||||
@@ -481,33 +482,41 @@ export default {
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; /* 用省略号表示溢出的文本 */
|
||||
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;
|
||||
@@ -515,17 +524,21 @@ export default {
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -172,6 +172,13 @@ export default {
|
||||
],
|
||||
Phone: [
|
||||
{ required: true, validator: checkPhone, trigger: 'blur' }
|
||||
],
|
||||
Email: [
|
||||
{
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: 'Please input the correct email address',
|
||||
trigger: 'blur,change',
|
||||
}
|
||||
]
|
||||
},
|
||||
siteOptions: [],
|
||||
|
||||
@@ -117,6 +117,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.Email && reg.test(this.form.Email)) {
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
|
||||
@@ -136,6 +136,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.Email && reg.test(this.form.Email)) {
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
|
||||
@@ -158,6 +158,9 @@ export default {
|
||||
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
|
||||
} else {
|
||||
var reg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
|
||||
callback()
|
||||
} else {
|
||||
@@ -170,6 +173,9 @@ export default {
|
||||
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
|
||||
} else {
|
||||
var reg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.ReplaceUserEmailOrPhone && reg.test(this.form.ReplaceUserEmailOrPhone)) {
|
||||
callback()
|
||||
} else {
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
<el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
|
||||
</el-form-item>
|
||||
<!-- 联系邮箱 -->
|
||||
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')">
|
||||
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="Email">
|
||||
<el-input v-model="form.Email" disabled />
|
||||
</el-form-item>
|
||||
|
||||
@@ -183,6 +183,13 @@ export default {
|
||||
],
|
||||
Phone: [
|
||||
{ required: true, validator: checkPhone, trigger: 'blur' }
|
||||
],
|
||||
Email: [
|
||||
{
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: 'Please input the correct email address',
|
||||
trigger: 'blur,change',
|
||||
}
|
||||
]
|
||||
},
|
||||
siteOptions: [],
|
||||
|
||||
@@ -108,6 +108,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.Email && reg.test(this.form.Email)) {
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
|
||||
@@ -139,6 +139,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.Email && reg.test(this.form.Email)) {
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
|
||||
@@ -131,6 +131,9 @@ export default {
|
||||
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
|
||||
} else {
|
||||
var reg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
|
||||
// this.sendDisabled = false
|
||||
callback()
|
||||
@@ -145,6 +148,9 @@ export default {
|
||||
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
|
||||
} else {
|
||||
var reg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.ReplaceUserEmailOrPhone && reg.test(this.form.ReplaceUserEmailOrPhone)) {
|
||||
callback()
|
||||
} else {
|
||||
|
||||
@@ -110,6 +110,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
@@ -125,6 +128,9 @@ export default {
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (
|
||||
this.form.ReplaceUserEmailOrPhone &&
|
||||
reg.test(this.form.ReplaceUserEmailOrPhone)
|
||||
|
||||
@@ -285,7 +285,8 @@ export default {
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
// type: 'email',
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: 'Please input the correct email address',
|
||||
trigger: 'blur,change',
|
||||
},
|
||||
|
||||
@@ -254,7 +254,7 @@
|
||||
<el-date-picker
|
||||
v-model="form.StartTime"
|
||||
type="year"
|
||||
value-format="yyyy-MM-DD"
|
||||
value-format="yyyy"
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
@@ -265,7 +265,7 @@
|
||||
<el-date-picker
|
||||
v-model="form.EndTime"
|
||||
type="year"
|
||||
value-format="yyyy-MM-DD"
|
||||
value-format="yyyy"
|
||||
>
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
@@ -904,12 +904,23 @@ export default {
|
||||
try {
|
||||
if (key === 'clinicalTrials') {
|
||||
let validate = await this.$refs.clinicalTrialsFrom.validate()
|
||||
console.log(validate, 'validate')
|
||||
if (!validate) return false
|
||||
this.form.DoctorId = this.reviewerId
|
||||
if (this.trialId) {
|
||||
this.form.TrialId = this.trialId
|
||||
}
|
||||
if (this.form.StartTime) {
|
||||
let arr = this.form.StartTime.split("-")
|
||||
if (arr.length <= 1) {
|
||||
this.form.StartTime = `${this.form.StartTime}-01-01`
|
||||
}
|
||||
}
|
||||
if (this.form.EndTime) {
|
||||
let arr = this.form.EndTime.split("-")
|
||||
if (arr.length <= 1) {
|
||||
this.form.EndTime = `${this.form.EndTime}-12-31`
|
||||
}
|
||||
}
|
||||
this.loading = true
|
||||
let res = await addOrUpdateTrialExperience(this.form)
|
||||
this.loading = false
|
||||
|
||||
@@ -38,7 +38,11 @@
|
||||
<span v-if="isEN">{{ DATA.DepartmentOther }}</span>
|
||||
<span v-else>{{ DATA.DepartmentOtherCN }}</span>
|
||||
</span>
|
||||
<span class="el-icon-user" v-if="DATA.Rank || DATA.RankCN">
|
||||
<span class="el-icon-user" v-if="DATA.RankOther || DATA.RankOtherCN">
|
||||
<span v-if="isEN">{{ DATA.RankOther }}</span>
|
||||
<span v-else>{{ DATA.RankOtherCN }}</span>
|
||||
</span>
|
||||
<span class="el-icon-user" v-else-if="DATA.Rank || DATA.RankCN">
|
||||
<span v-if="isEN">{{ DATA.Rank }}</span>
|
||||
<span v-else>{{ DATA.RankCN }}</span>
|
||||
</span>
|
||||
@@ -327,7 +331,13 @@
|
||||
:label="$t('curriculumVitae:info:form:physician')"
|
||||
prop="RankId"
|
||||
>
|
||||
<el-select v-model="form.RankId" clearable placeholder="">
|
||||
<el-select v-model="form.RankId" clearable placeholder="" @change="()=>{
|
||||
if($fd('Rank', form.RankId, 'id') !==
|
||||
$t('curriculumVitae:selectLabel:Other')){
|
||||
form.RankOther = null
|
||||
form.RankOtherCN = null
|
||||
}
|
||||
}">
|
||||
<el-option
|
||||
v-for="item in $d.Rank"
|
||||
:key="item.id"
|
||||
@@ -548,7 +558,8 @@ export default {
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
// type: 'email',
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: this.$t('rules:email'),
|
||||
trigger: 'blur,change',
|
||||
},
|
||||
|
||||
@@ -72,7 +72,11 @@
|
||||
reviewerData.EmploymentView.DepartmentOtherCN
|
||||
}}</span>
|
||||
</span>
|
||||
<span class="el-icon-user"
|
||||
<span class="el-icon-user" v-if="reviewerData.EmploymentView.RankOther || reviewerData.EmploymentView.RankOtherCN">
|
||||
<span v-if="isEN">{{ reviewerData.EmploymentView.RankOther }}</span>
|
||||
<span v-else>{{ reviewerData.EmploymentView.RankOtherCN }}</span>
|
||||
</span>
|
||||
<span class="el-icon-user" v-else
|
||||
><span v-if="isEN">{{ reviewerData.EmploymentView.Rank }}</span>
|
||||
<span v-else>{{ reviewerData.EmploymentView.RankCN }}</span></span
|
||||
>
|
||||
@@ -417,7 +421,12 @@
|
||||
v-if="true"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ $fd('Indication', scope.row.IndicationEnum) }}</span>
|
||||
<span v-if="scope.row.EvaluationContent">
|
||||
{{ scope.row.EvaluationContent }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ $fd('Indication', scope.row.IndicationEnum) }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
|
||||
@@ -530,6 +530,9 @@ export default {
|
||||
emailList.forEach((item) => {
|
||||
var pattern =
|
||||
/^([A-Za-z0-9_\-\.\u4e00-\u9fa5])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,8})$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
pattern = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (!pattern.test(item)) {
|
||||
isError = true
|
||||
}
|
||||
|
||||
@@ -439,7 +439,8 @@ export default {
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
// type: 'email',
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: 'Please input the correct email address',
|
||||
trigger: ['blur'],
|
||||
},
|
||||
|
||||
@@ -219,6 +219,13 @@ export default {
|
||||
sortable: 'custom',
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
{
|
||||
prop: 'JoinedTrialCount',
|
||||
label: this.$t('system:userlist:table:JoinedTrialCount'),
|
||||
minWidth: 150,
|
||||
sortable: 'custom',
|
||||
showOverflowTooltip: true,
|
||||
},
|
||||
{
|
||||
prop: 'LastLoginTime',
|
||||
label: this.$t('system:userlist:table:LastLoginTime'),
|
||||
|
||||
@@ -289,7 +289,10 @@ export default {
|
||||
},
|
||||
handleEmailChange() {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
reg = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (this.userForm.EMail && reg.test(this.userForm.EMail)) {
|
||||
this.sendDisabled = false
|
||||
} else {
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
<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 :label="$t('trials:signRecords:table:userType')" v-if="!isDoc && !isEASystem">
|
||||
<el-select v-model="searchData.UserTypeId" clearable filterable style="width: 120px">
|
||||
<el-option v-for="item of userTypeOptions"
|
||||
v-show="isSystem || (item.UserTypeEnum !== 26 && item.UserTypeEnum !== 27)" :key="item.Id"
|
||||
@@ -69,7 +69,7 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:signRecords:table:isSign')" v-if="!isDoc || !viewStatus">
|
||||
<el-form-item :label="$t('trials:signRecords:table:isSign')" v-if="(!isDoc || !viewStatus) && !isEASystem">
|
||||
<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" />
|
||||
@@ -78,12 +78,12 @@
|
||||
<el-form-item :label="isDoc
|
||||
? $t('trials:signRecords:table:isDeletedFile')
|
||||
: $t('trials:signRecords:table:isDeleted')
|
||||
">
|
||||
" v-if="!isEASystem">
|
||||
<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-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 && !isEASystem">
|
||||
<el-input v-model="searchData.UserName" style="width: 120px" />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:signRecords:table:confirmTime')" v-if="isDoc || isSystem">
|
||||
@@ -91,7 +91,7 @@
|
||||
:default-time="['00:00:00', '23:59:59']" type="datetimerange">
|
||||
</el-date-picker>
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:signRecords:table:uploadTime')" v-if="isSystem">
|
||||
<el-form-item :label="$t('trials:signRecords:table:uploadTime')" v-if="isSystem && !isEASystem">
|
||||
<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>
|
||||
@@ -305,6 +305,11 @@ export default {
|
||||
},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
isEASystem() {
|
||||
return this.isSystem && this.hasPermi(['role:ea'])
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getTypeOptions()
|
||||
this.getUserSelect()
|
||||
@@ -360,6 +365,14 @@ export default {
|
||||
},
|
||||
// 获取系统文件数据
|
||||
getList() {
|
||||
if (this.isEASystem) {
|
||||
this.searchData.IsConfirmed = true
|
||||
if (!this.searchData.FileTypeId && !this.searchData.Name && !this.searchData.UserId && !this.searchData.userName && (!Array.isArray(this.timeList) || this.timeList.length < 2)) {
|
||||
this.list = []
|
||||
this.total = 0
|
||||
return false
|
||||
}
|
||||
}
|
||||
this.loading = true
|
||||
if (this.viewStatus) {
|
||||
this.searchData.IsConfirmed = true
|
||||
@@ -398,6 +411,7 @@ export default {
|
||||
getTypeOptions() {
|
||||
if (this.isSystem) {
|
||||
this.typeOptions = this.$d.Sys_Document
|
||||
if (this.isEASystem) this.typeOptions = this.typeOptions.filter(item => item.raw.ChildGroup !== "Trial")
|
||||
} else {
|
||||
getTrialDocAndSystemDocType(this.trialId).then((res) => {
|
||||
this.typeOptions = res.Result
|
||||
|
||||
@@ -535,7 +535,8 @@ export default {
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
type: 'email',
|
||||
// type: 'email',
|
||||
pattern: new RegExp(this.$reg().EmailRegexStr),
|
||||
message: this.$t('rules:email'),
|
||||
trigger: 'blur,change',
|
||||
},
|
||||
@@ -610,6 +611,9 @@ export default {
|
||||
emailList.forEach((item) => {
|
||||
var pattern =
|
||||
/^([A-Za-z0-9_\-\.\u4e00-\u9fa5])+\@([A-Za-z0-9_\-\.])+\.([A-Za-z]{2,8})$/
|
||||
if (this.$reg().EmailRegexStr) {
|
||||
pattern = new RegExp(this.$reg().EmailRegexStr)
|
||||
}
|
||||
if (!pattern.test(item)) {
|
||||
isError = true
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<el-table-column prop="Name" :label="$t('trials:self-attachment:table:fileName')" show-overflow-tooltip
|
||||
sortable="custom" />
|
||||
<el-table-column :label="$t('trials:self-attachment:table:AttachmentCount')" prop="AttachmentCount"
|
||||
show-overflow-tooltip sortable="custom">
|
||||
show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click.stop="openAttachment(scope.row, true)">{{ scope.row.AttachmentCount
|
||||
}}</el-button>
|
||||
|
||||
@@ -842,7 +842,7 @@ export default {
|
||||
var trialId = this.$route.query.trialId
|
||||
var file = await this.fileToBlob(param.file)
|
||||
const res = await this.OSSclient.put(
|
||||
`/${trialId}/Read/${this.subjectId}/visit/${param.file.name}`,
|
||||
`/${trialId}/Read/${this.subjectId}/${this.visitTaskId}/${param.file.name}`,
|
||||
file
|
||||
)
|
||||
console.log(res)
|
||||
|
||||
@@ -1,63 +1,56 @@
|
||||
<template>
|
||||
<div
|
||||
id="canvas"
|
||||
ref="canvas"
|
||||
v-loading="loading"
|
||||
element-loading-text="Loading..."
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
style="position:relative;"
|
||||
class="cornerstone-element"
|
||||
@mouseup="sliderMouseup"
|
||||
@contextmenu.prevent="onContextmenu"
|
||||
>
|
||||
<div id="canvas" ref="canvas" v-loading="loading" :element-loading-text="NSTip"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)" style="position:relative;" class="cornerstone-element"
|
||||
@mouseup="sliderMouseup" @contextmenu.prevent="onContextmenu">
|
||||
<!-- 临床数据 -->
|
||||
<div v-if="stack.isExistsClinicalData" class="info-cd" @click.stop="handleViewCD($event)">
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:clinicalData')" placement="bottom">
|
||||
<svg-icon icon-class="documentation" class="svg-icon" />
|
||||
</el-tooltip>
|
||||
|
||||
</div>
|
||||
<!-- 检查部位 -->
|
||||
<div v-if="CriterionType == 19 || CriterionType == 20"
|
||||
:class="{ 'info-cd': true, 'info-cd2': stack.isExistsClinicalData }" @click.stop="handleViewBP($event)">
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:BodyPart')" placement="bottom">
|
||||
<!-- <svg-icon icon-class="documentation" class="svg-icon" /> -->
|
||||
<i class="el-icon-tickets"></i>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<!-- 切换访视 -->
|
||||
<div
|
||||
v-if="stack.imageRendered && isReadingTaskViewInOrder === 1"
|
||||
class="info-visit"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<div
|
||||
class="arrw_div_wrapper"
|
||||
:style="{cursor:stack.visitTaskNum <= minVistNum?'not-allowed':'pointer',color:stack.visitTaskNum <= minVistNum?'#888':'#fff'}"
|
||||
@click.stop.prevent="toggleSeries($event,-1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<div v-if="stack.imageRendered && isReadingTaskViewInOrder === 1" class="info-visit"
|
||||
@dblclick.stop="preventDefault($event)">
|
||||
<div class="arrw_div_wrapper"
|
||||
:style="{ cursor: stack.visitTaskNum <= minVistNum ? 'not-allowed' : 'pointer', color: stack.visitTaskNum <= minVistNum ? '#888' : '#fff' }"
|
||||
@click.stop.prevent="toggleSeries($event, -1)" @dblclick.stop="preventDefault($event)">
|
||||
<i class="el-icon-caret-left" />
|
||||
</div>
|
||||
<div class="blind_name_wrapper">
|
||||
{{ stack.taskBlindName }}
|
||||
</div>
|
||||
<div
|
||||
class="arrw_div_wrapper"
|
||||
:style="{cursor:stack.visitTaskNum >= maxVistNum?'not-allowed':'pointer',color:stack.visitTaskNum >= maxVistNum?'#888':'#fff'}"
|
||||
@click.stop.prevent="toggleSeries($event,1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<div class="arrw_div_wrapper"
|
||||
:style="{ cursor: stack.visitTaskNum >= maxVistNum ? 'not-allowed' : 'pointer', color: stack.visitTaskNum >= maxVistNum ? '#888' : '#fff' }"
|
||||
@click.stop.prevent="toggleSeries($event, 1)" @dblclick.stop="preventDefault($event)">
|
||||
<i class="el-icon-caret-right" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-series">
|
||||
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{ stack.taskBlindName }}</h2>
|
||||
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{
|
||||
stack.taskBlindName }}</h2>
|
||||
<div v-show="dicomInfo.series">Series: #{{ dicomInfo.series }}</div>
|
||||
<div>Image: #{{ dicomInfo.frame }}</div>
|
||||
<div>{{ dicomInfo.modality }}</div>
|
||||
</div>
|
||||
<div class="info-image">
|
||||
<div v-show="mousePosition.mo">
|
||||
Pos: {{ mousePosition.x?mousePosition.x.toFixed(0):'' }}, {{ mousePosition.y?mousePosition.y.toFixed(0):'' }}
|
||||
Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) :
|
||||
'' }}
|
||||
</div>
|
||||
<div v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
||||
<div
|
||||
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
||||
HU: {{ mousePosition.mo }}
|
||||
</div>
|
||||
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ?mousePosition.suv.toFixed(3) :mousePosition.suv.toFixed(digitPlaces) }}
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ? mousePosition.suv.toFixed(3) : mousePosition.suv.toFixed(digitPlaces) }}
|
||||
</div>
|
||||
<div v-else-if="mousePosition.mo">
|
||||
Density: {{ mousePosition.mo }}
|
||||
@@ -81,8 +74,12 @@
|
||||
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
|
||||
<!-- <div>{{ dicomInfo.time }}</div> -->
|
||||
</div>
|
||||
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 140px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer" @click.stop="goViewer($event)">
|
||||
<div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event)" />
|
||||
<div ref="sliderBox" class="my_slider_box"
|
||||
style="position: absolute;right: 1px;height: calc(100% - 140px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer"
|
||||
@click.stop="goViewer($event)">
|
||||
<div :style="{ top: height + '%' }"
|
||||
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
|
||||
@click.stop.prevent="() => { return }" @mousedown.stop="sliderMousedown($event)" />
|
||||
</div>
|
||||
<div style="position: absolute;left: 50%;top: 30px;color: #f44336;transform: translateX(-50%);">
|
||||
{{ markers.top }}
|
||||
@@ -117,7 +114,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.my_slider_box:after{
|
||||
.my_slider_box:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
@@ -308,7 +305,10 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList', 'currentReadingTaskState'])
|
||||
...mapGetters(['visitTaskList', 'currentReadingTaskState']),
|
||||
NSTip() {
|
||||
return `NS: ${this.$store.state.trials.downloadTip}`
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentReadingTaskState: {
|
||||
@@ -572,7 +572,7 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
|
||||
}).catch(() => {})
|
||||
}).catch(() => { })
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
@@ -1111,7 +1111,7 @@ export default {
|
||||
var frame = imageInfo.frame
|
||||
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
|
||||
this.stack.instanceId = instanceId
|
||||
|
||||
|
||||
const element = this.$refs.canvas
|
||||
cornerstone.enable(element)
|
||||
element.tabIndex = 0
|
||||
@@ -1165,7 +1165,7 @@ export default {
|
||||
|
||||
// const scope = this
|
||||
Array.from(toolButtons).forEach((toolBtn) => {
|
||||
// Add the tool
|
||||
// Add the tool
|
||||
const toolName = toolBtn.getAttribute('data-tool')
|
||||
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
||||
if (apiTool) {
|
||||
@@ -1173,17 +1173,17 @@ export default {
|
||||
|
||||
if (!toolAlreadyAddedToElement) {
|
||||
if (toolName === 'Length') {
|
||||
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true }})
|
||||
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true } })
|
||||
} else if (toolName === 'Bidirectional') {
|
||||
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
|
||||
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
|
||||
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true }})
|
||||
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
|
||||
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
|
||||
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true } })
|
||||
} else if (toolName === 'ArrowAnnotate') {
|
||||
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
|
||||
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true } })
|
||||
} else if (toolName === 'RectangleRoi') {
|
||||
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
|
||||
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true } })
|
||||
} else if (toolName === 'Probe' && parseInt(localStorage.getItem('CriterionType')) === 21) {
|
||||
cornerstoneTools.addToolForElement(element, ProbeTool, { configuration: { fixedRadius: 5, handleRadius: true, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces }})
|
||||
cornerstoneTools.addToolForElement(element, ProbeTool, { configuration: { fixedRadius: 5, handleRadius: true, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces } })
|
||||
} else {
|
||||
cornerstoneTools.addToolForElement(element, apiTool)
|
||||
}
|
||||
@@ -1209,10 +1209,10 @@ export default {
|
||||
mouseButtonMask: 4
|
||||
})
|
||||
|
||||
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
|
||||
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
|
||||
// }
|
||||
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
|
||||
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
|
||||
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
|
||||
// }
|
||||
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
|
||||
}
|
||||
|
||||
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
|
||||
@@ -1229,7 +1229,7 @@ export default {
|
||||
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
|
||||
this.stack.instanceId = instanceId
|
||||
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
|
||||
|
||||
|
||||
resolve()
|
||||
})
|
||||
},
|
||||
@@ -1257,9 +1257,8 @@ export default {
|
||||
data.string('x00080030')
|
||||
)
|
||||
this.dicomInfo.series = data.string('x00200011')
|
||||
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${
|
||||
this.stack.imageIds.length
|
||||
}`
|
||||
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${this.stack.imageIds.length
|
||||
}`
|
||||
this.dicomInfo.size = `${data.uint16('x00280011')}*${data.uint16(
|
||||
'x00280010'
|
||||
)}`
|
||||
@@ -1462,9 +1461,9 @@ export default {
|
||||
var element = cornerstone.getEnabledElement(this.canvas)
|
||||
const { rowPixelSpacing, colPixelSpacing } = this.getPixelSpacing(element.image)
|
||||
const dx =
|
||||
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
|
||||
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
|
||||
const dy =
|
||||
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
|
||||
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
|
||||
const length = Math.sqrt(dx * dx + dy * dy)
|
||||
|
||||
return length.toFixed(this.digitPlaces)
|
||||
@@ -1478,9 +1477,9 @@ export default {
|
||||
if (imagePlane) {
|
||||
return {
|
||||
rowPixelSpacing:
|
||||
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
|
||||
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
|
||||
colPixelSpacing:
|
||||
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
|
||||
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1537,7 +1536,7 @@ export default {
|
||||
},
|
||||
debounce(callback, delay) {
|
||||
let timerId
|
||||
return function() {
|
||||
return function () {
|
||||
clearTimeout(timerId)
|
||||
timerId = setTimeout(() => {
|
||||
callback.apply(this, arguments)
|
||||
@@ -2013,95 +2012,114 @@ export default {
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
handleViewBP(e) {
|
||||
DicomEvent.$emit('previewBP', this.stack.visitTaskId)
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.context-menu-wrapper{
|
||||
position: absolute;
|
||||
ul{
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
.context-menu-wrapper {
|
||||
position: absolute;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
background: #343333;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 3px;
|
||||
height: auto;
|
||||
min-height: 50px;
|
||||
line-height: 1.5em;
|
||||
width: 80px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.menu {
|
||||
li {
|
||||
padding: 2px 5px;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #666;
|
||||
|
||||
div {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.submenu {
|
||||
position: absolute;
|
||||
left: 77px;
|
||||
top: -1px;
|
||||
background: #343333;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 3px;
|
||||
height: auto;
|
||||
min-height: 50px;
|
||||
line-height: 1.5em;
|
||||
width:80px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.menu{
|
||||
display: none;
|
||||
|
||||
li {
|
||||
padding: 2px 5px;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #666;
|
||||
div{
|
||||
|
||||
div {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.submenu{
|
||||
position: absolute;
|
||||
left: 77px;
|
||||
top: -1px;
|
||||
background: #343333;
|
||||
color: #fff;
|
||||
display: none;
|
||||
li {
|
||||
padding: 2px 5px;
|
||||
border-bottom: 1px solid #666;
|
||||
div{
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.menu li:hover{
|
||||
background-color: #ff5722;
|
||||
.submenu{
|
||||
display:block;
|
||||
}
|
||||
}
|
||||
.menu_active{
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu_disabled{
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
}
|
||||
.info-visit{
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.arrw_div_wrapper{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
.blind_name_wrapper{
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding:0 10px;
|
||||
font-size: 14px;
|
||||
|
||||
.menu li:hover {
|
||||
background-color: #ff5722;
|
||||
|
||||
.submenu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.info-cd{
|
||||
|
||||
.menu_active {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu_disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.info-visit {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.arrw_div_wrapper {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
|
||||
.blind_name_wrapper {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding: 0 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.info-cd {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 5px;
|
||||
@@ -2110,6 +2128,11 @@ export default {
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.info-cd2 {
|
||||
left: 35px;
|
||||
}
|
||||
|
||||
.info-series {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
@@ -2119,6 +2142,7 @@ export default {
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.info-image {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
@@ -2138,6 +2162,7 @@ export default {
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.info-instance {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
@@ -2170,6 +2195,7 @@ export default {
|
||||
margin: 10px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.menu__item:hover {
|
||||
color: #ff0000;
|
||||
}
|
||||
@@ -2189,11 +2215,12 @@ li:hover {
|
||||
background-color: #e0e0e2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.msg-div {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
color: #000;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
color: #000;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -475,6 +475,7 @@
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
@handleReadingChart="handleReadingChart"
|
||||
/>
|
||||
|
||||
<IVUSList
|
||||
@@ -1229,6 +1230,9 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
handleReadingChart(e) {
|
||||
this.$emit('handleReadingChart', e)
|
||||
},
|
||||
getTrialCriterion() {
|
||||
getCriterionReadingInfo({
|
||||
TrialId: this.trialId || this.$route.query.trialId,
|
||||
|
||||
@@ -721,7 +721,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
+1
-1
@@ -739,7 +739,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -872,7 +872,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
<div class="add-icon" @click.prevent="downloadTpl">
|
||||
<i class="el-icon-download" />
|
||||
</div>
|
||||
<div class="add-icon" style="margin: 0 5px;" @click.prevent="uploadTpl(item.LesionType)">
|
||||
<div class="add-icon" style="margin: 0 5px;"
|
||||
@click.prevent="uploadTpl(item.LesionType, item.QuestionName)">
|
||||
<i class="el-icon-upload2" />
|
||||
</div>
|
||||
<div class="add-icon" @click.prevent="handleAddOrEdit('add', item)">
|
||||
@@ -64,20 +65,25 @@
|
||||
{{ `${scope.row[q.Id]} ${$fd('ValueUnit', parseInt(q.Unit))}` }}
|
||||
</span>
|
||||
<span v-else-if="q.DictionaryCode">
|
||||
{{ `${$fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}` }}
|
||||
{{`${scope.row[q.Id] instanceof Array ? scope.row[q.Id].map(item => $fd(q.DictionaryCode,
|
||||
parseInt(item))).join(',') : $fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}`}}
|
||||
</span>
|
||||
<span v-else-if="q.OptionTypeEnum === 1">
|
||||
{{ `${scope.row[q.Id] instanceof Array ? scope.row[q.Id].join(',') : scope.row[q.Id]}` }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ `${scope.row[q.Id]}` }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="readingTaskState < 2 && item.LesionType === 102"
|
||||
<el-table-column v-if="readingTaskState < 2 && (item.LesionType === 102 || item.LesionType === 103)"
|
||||
:label="$t('common:action:action')" width="90px" fixed="right">
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="handleAddOrEdit('edit', item, scope.$index)">
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDelete(item, scope.$index)">
|
||||
<el-button type="text" size="mini" @click="handleDelete(item, scope.$index)"
|
||||
v-if="item.LesionType === 102">
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -106,7 +112,7 @@
|
||||
</template>
|
||||
<template v-if="item.Type === 'select'">
|
||||
<el-select v-model="questionForm[item.Id]" :disabled="!isCurrentTask || readingTaskState >= 2"
|
||||
@change="((val) => { formItemChange(val, item) })">
|
||||
:multiple="item.OptionTypeEnum === 1" @change="((val) => { formItemChange(val, item) })">
|
||||
<el-option v-for="dict of $d[item.DictionaryCode]" :key="dict.id" :value="String(dict.value)"
|
||||
:label="dict.label" />
|
||||
</el-select>
|
||||
@@ -115,10 +121,10 @@
|
||||
<template v-if="item.Childrens && item.Childrens.length > 0">
|
||||
<template v-for="child in item.Childrens">
|
||||
<el-form-item :key="child.Id"
|
||||
v-if="(child.ShowQuestion === 1 && child.ParentTriggerValueList.includes(String(questionForm[item.Id]))) || child.ShowQuestion === 0"
|
||||
v-if="(child.ShowQuestion === 1 && (child.ParentTriggerValueList.includes(String(questionForm[item.Id])) || (Array.isArray(questionForm[item.Id]) && child.ParentTriggerValueList.some(da => questionForm[item.Id].includes(da))))) || child.ShowQuestion === 0"
|
||||
:label="`${child.QuestionName}`" :prop="child.Id" :rules="[
|
||||
{
|
||||
required: (child.IsRequired === 0 || (child.IsRequired === 1 && child.RelevanceId && (child.RelevanceValue.includes(questionForm[child.RelevanceId])))) && child.Type !== 'group' && child.Type !== 'summary',
|
||||
required: (child.IsRequired === 0 || (child.IsRequired === 1 && child.RelevanceId && ((child.RelevanceValue.includes(questionForm[child.RelevanceId])) || (Array.isArray(questionForm[child.RelevanceId]) && child.RelevanceValueList.some(da => questionForm[child.RelevanceId].includes(da)))))) && child.Type !== 'group' && child.Type !== 'summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(child.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||
},
|
||||
]">
|
||||
@@ -174,7 +180,8 @@
|
||||
<!-- 导入 -->
|
||||
<el-dialog v-if="upload.visible" :visible.sync="upload.visible" :close-on-click-modal="false"
|
||||
:title="upload.title" width="500px">
|
||||
<UploadExcel :visit-task-id="visitTaskId" @close="uploadDlgClose" />
|
||||
<UploadExcel :visit-task-id="visitTaskId" :TableName="upload.TableName" :lesion-type="upload.lesionType"
|
||||
@close="uploadDlgClose" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
@@ -232,8 +239,8 @@ export default {
|
||||
questionForm: {},
|
||||
formChanged: false,
|
||||
digitPlaces: 2,
|
||||
addOrEdit: { visible: false, title: '' },
|
||||
upload: { visible: false, title: '' },
|
||||
addOrEdit: { visible: false, title: '', lesionType: null },
|
||||
upload: { visible: false, title: '', TableName: '', lesionType: null },
|
||||
qsList: [],
|
||||
answersList: [],
|
||||
qsForm: {},
|
||||
@@ -323,7 +330,7 @@ export default {
|
||||
const type = ['number', 'radio', 'select', 'input', 'textarea', 'calculation']
|
||||
questions.forEach(item => {
|
||||
if (type.includes(item.Type)) {
|
||||
const answer = item.Type === 'number' || item.Type === 'calculation' ? isNaN(parseFloat(item.Answer)) ? null : parseFloat(item.Answer) : item.Answer
|
||||
const answer = item.Type === 'select' && item.OptionTypeEnum === 1 && item.Answer ? JSON.parse(item.Answer) : item.Type === 'number' || item.Type === 'calculation' ? isNaN(parseFloat(item.Answer)) ? null : parseFloat(item.Answer) : item.Answer
|
||||
this.$set(this.questionForm, item.Id, answer)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
@@ -483,7 +490,7 @@ export default {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
answers.push({ id: k, answer: Array.isArray(this.questionForm[k]) ? JSON.stringify(this.questionForm[k]) : this.questionForm[k] })
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
@@ -595,6 +602,7 @@ export default {
|
||||
this.$set(this.qsForm, i.Id, v)
|
||||
})
|
||||
this.addOrEdit.visible = true
|
||||
this.addOrEdit.lesionType = row.LesionType
|
||||
},
|
||||
async saveFormData() {
|
||||
const valid = await this.$refs.tableQsForm.validate()
|
||||
@@ -606,7 +614,7 @@ export default {
|
||||
for (const k in this.qsForm) {
|
||||
if (reg.test(k)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
|
||||
answers.push({ tableQuestionId: k, answer: this.qsForm[k] })
|
||||
answers.push({ tableQuestionId: k, answer: Array.isArray(this.qsForm[k]) ? JSON.stringify(this.qsForm[k]) : this.qsForm[k] })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -619,6 +627,9 @@ export default {
|
||||
trialId: this.trialId,
|
||||
answerList: answers
|
||||
}
|
||||
if (this.addOrEdit.lesionType === 103) {
|
||||
params.computationTrigger = 9
|
||||
}
|
||||
const res = await submitTableQuestion(params)
|
||||
if (res.IsSuccess) {
|
||||
// this.refreshQuestions()
|
||||
@@ -668,7 +679,9 @@ export default {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
uploadTpl(lesionType) {
|
||||
uploadTpl(lesionType, TableName) {
|
||||
this.upload.lesionType = lesionType
|
||||
this.upload.TableName = TableName
|
||||
this.upload.title = `导入( ${this.$fd('LesionType', lesionType)} )`
|
||||
this.upload.visible = true
|
||||
},
|
||||
|
||||
+61
-122
@@ -1,119 +1,66 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<div v-if="!!question.GroupName && question.Type === 'group'">
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
{{ 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']},
|
||||
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' : '']"
|
||||
>
|
||||
: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-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-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]"
|
||||
<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)})"
|
||||
>
|
||||
clearable :multiple="question.OptionTypeEnum === 1" @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]"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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
|
||||
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"
|
||||
/>
|
||||
<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)})"
|
||||
>
|
||||
<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)"
|
||||
>
|
||||
<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"
|
||||
>
|
||||
<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"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
<el-checkbox-group v-else-if="question.Type === 'checkbox'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2" @change="((val) => { formItemChange(val, question) })">
|
||||
<el-checkbox v-for="val in question.TypeValue.split('|')" :key="val" :label="val">
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
@@ -144,24 +91,15 @@
|
||||
/>
|
||||
</template> -->
|
||||
<!-- 数值类型 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='number'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState>=2 "
|
||||
type="number"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-input v-else-if="question.Type === 'number'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2" type="number" @change="((val) => { formItemChange(val, question) })">
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-input v-else-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled
|
||||
@change="((val) => { formItemChange(val, question) })">
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
@@ -169,15 +107,9 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<QuestionTableFormItem
|
||||
v-for="item in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
<QuestionTableFormItem v-for="item in question.Childrens" :key="item.Id" :question="item"
|
||||
:question-form="questionForm" :reading-task-state="readingTaskState" @setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -269,29 +201,36 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
.mb {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
|
||||
.disabled {
|
||||
::v-deep .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
|
||||
.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-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;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,30 +1,15 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="uploadExcel"
|
||||
class="upload-excel-file"
|
||||
>
|
||||
<el-form ref="uploadExcel" class="upload-excel-file">
|
||||
<!-- 文件 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:label:file')">
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
accept=".xlsx,.xls,.csv"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile"
|
||||
:on-preview="handlePreview"
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
<el-upload class="upload-demo" action accept=".xlsx,.xls,.csv" :before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile" :on-preview="handlePreview" :show-file-list="true" :limit="1"
|
||||
:on-exceed="handleExceed">
|
||||
<el-button size="small" type="primary">
|
||||
{{ $t('trials:consistencyCheck:dialogButton:upload') }}
|
||||
</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:consistencyCheck:message:excelFileOnly') }})
|
||||
</span>
|
||||
</el-upload>
|
||||
@@ -33,12 +18,20 @@
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadIVUSTemplate } from '@/api/reading'
|
||||
import { readingImport } from '@/api/reading'
|
||||
export default {
|
||||
props: {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
lesionType: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
TableName: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -63,7 +56,9 @@ export default {
|
||||
var data = new FormData()
|
||||
data.append('file', param.file)
|
||||
data.append('visitTaskId', this.visitTaskId)
|
||||
await uploadIVUSTemplate(data)
|
||||
data.append('readingImportType', 0)
|
||||
data.append('TableName', this.TableName)
|
||||
await readingImport(data)
|
||||
this.$emit('close')
|
||||
this.$message.success('导入成功!')
|
||||
loading.close()
|
||||
@@ -95,21 +90,24 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-excel-file{
|
||||
.upload-excel-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{
|
||||
|
||||
.account_item_clear {
|
||||
.el-tag__close {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1073,7 +1073,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -715,7 +715,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
<template>
|
||||
<div v-loading="loading" style="width:100%;height:100%;">
|
||||
<transition name="viewer-fade">
|
||||
<div v-show="urlList.length > 0" ref="image-viewer__wrapper" tabindex="-1" class="image-viewer__wrapper" :style="{ 'z-index':5 }">
|
||||
<div v-show="urlList.length > 0" ref="image-viewer__wrapper" tabindex="-1" class="image-viewer__wrapper"
|
||||
:style="{ 'z-index': 5 }">
|
||||
<span class="image-viewer_desc">
|
||||
<!-- <span v-if="studyCode">NST00006</span>
|
||||
<span v-if="modality">CT</span>
|
||||
<span v-if="bodyPart">上/下腹部</span><br> -->
|
||||
{{ `${index+1} / ${urlList.length}` }}
|
||||
{{ `${index + 1} / ${urlList.length}` }}
|
||||
</span>
|
||||
<!-- 关闭 -->
|
||||
<span class="image-viewer__btn image-viewer__close" @click="hide">
|
||||
@@ -15,18 +16,12 @@
|
||||
</span>
|
||||
<!-- Arrow -->
|
||||
<template v-if="!isSingle">
|
||||
<span
|
||||
class="image-viewer__btn image-viewer__prev"
|
||||
:class="{ 'is-disabled': !infinite && isFirst }"
|
||||
@click="prev"
|
||||
>
|
||||
<span class="image-viewer__btn image-viewer__prev" :class="{ 'is-disabled': !infinite && isFirst }"
|
||||
@click="prev">
|
||||
<i class="el-icon-arrow-left" />
|
||||
</span>
|
||||
<span
|
||||
class="el-image-viewer__btn el-image-viewer__next"
|
||||
:class="{ 'is-disabled': !infinite && isLast }"
|
||||
@click="next"
|
||||
>
|
||||
<span class="el-image-viewer__btn el-image-viewer__next" :class="{ 'is-disabled': !infinite && isLast }"
|
||||
@click="next">
|
||||
<i class="el-icon-arrow-right" />
|
||||
</span>
|
||||
</template>
|
||||
@@ -40,34 +35,25 @@
|
||||
<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')" />
|
||||
<i
|
||||
v-if="readingTaskState < 2"
|
||||
class="el-icon-bottom-right"
|
||||
:style="{cursor:isToolDisabled || readingTaskState >=2 ?'not-allowed':'pointer'}"
|
||||
@click="handleDrawArrow"
|
||||
/>
|
||||
<i v-if="readingTaskState < 2" class="el-icon-bottom-right"
|
||||
:style="{ cursor: isToolDisabled || readingTaskState >= 2 ? 'not-allowed' : 'pointer' }"
|
||||
@click="handleDrawArrow" />
|
||||
|
||||
<!-- <i
|
||||
class="rectangle"
|
||||
:style="{cursor:isToolDisabled || readingTaskState >=2 ?'not-allowed':'pointer'}"
|
||||
@click="handleDrawRectangle"
|
||||
/> -->
|
||||
<svg-icon v-if="readingTaskState < 2" icon-class="rectangle" class="svg-icon" :style="{cursor:isToolDisabled || readingTaskState >=2 ?'not-allowed':'pointer'}" @click="handleDrawRectangle" />
|
||||
<svg-icon v-if="readingTaskState < 2" icon-class="rectangle" class="svg-icon"
|
||||
:style="{ cursor: isToolDisabled || readingTaskState >= 2 ? 'not-allowed' : 'pointer' }"
|
||||
@click="handleDrawRectangle" />
|
||||
</div>
|
||||
</div>
|
||||
<!-- 图片 -->
|
||||
<div id="image-viewer__canvas" class="image-viewer__canvas">
|
||||
<canvas
|
||||
v-if="canvasSize.width && canvasPosition.y"
|
||||
id="canvas"
|
||||
:height="canvasSize.height"
|
||||
:width="canvasSize.width"
|
||||
:style="imgStyle"
|
||||
@mousedown="handleMouseDown"
|
||||
@mousemove="handleMouseMove"
|
||||
@mouseup="handleMouseUp"
|
||||
@contextmenu="handleContextmenu"
|
||||
/>
|
||||
<canvas v-if="canvasSize.width && canvasPosition.y" id="canvas" :height="canvasSize.height"
|
||||
:width="canvasSize.width" :style="imgStyle" @mousedown="handleMouseDown" @mousemove="handleMouseMove"
|
||||
@mouseup="handleMouseUp" @contextmenu="handleContextmenu" />
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -111,11 +97,11 @@ export default {
|
||||
},
|
||||
onSwitch: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
default: () => { }
|
||||
},
|
||||
onClose: {
|
||||
type: Function,
|
||||
default: () => {}
|
||||
default: () => { }
|
||||
},
|
||||
initialIndex: {
|
||||
type: Number,
|
||||
@@ -191,11 +177,15 @@ export default {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
this.reset()
|
||||
this.onSwitch(val)
|
||||
if (val >= 0) {
|
||||
this.imgId = this.urlList[val].Id
|
||||
this.onSwitch(this.imgId)
|
||||
|
||||
this.imgUrl = this.urlList[val].Path
|
||||
|
||||
this.loadImage()
|
||||
}
|
||||
|
||||
this.imgUrl = this.urlList[val].Path
|
||||
this.imgId = this.urlList[val].Id
|
||||
this.loadImage()
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -276,7 +266,7 @@ export default {
|
||||
window.opener.postMessage(data, window.location)
|
||||
},
|
||||
async receiveMsg(event) {
|
||||
console.log('nonedicoms', event.data.type)
|
||||
// console.log('nonedicoms', event.data.type)
|
||||
if (event.data.type === 'isCanActiveNoneDicomTool') {
|
||||
if (event.data.data.isCanActiveTool) {
|
||||
// this.model = 'ArrowAnnotate'
|
||||
@@ -304,8 +294,12 @@ export default {
|
||||
// this.canvasData.splice(i, 1)
|
||||
// }
|
||||
// }
|
||||
var idx = this.canvasData.findIndex(item => item.data.uuid === event.data.data.data.uuid)
|
||||
this.canvasData.splice(idx, 1)
|
||||
if (!event.data.data) {
|
||||
this.canvasData = []
|
||||
} else {
|
||||
var idx = this.canvasData.findIndex(item => item.data.uuid === event.data.data.data.uuid)
|
||||
this.canvasData.splice(idx, 1)
|
||||
}
|
||||
ctx.clearRect(0, 0, this.canvasSize.width, this.canvasSize.height) // 清除画布后立刻重新绘制视觉上形成动画
|
||||
await ctx.drawImage(
|
||||
this.currentImg,
|
||||
@@ -355,7 +349,7 @@ export default {
|
||||
y: canvasDiv.offsetHeight / 2 - img.height / 2 - 25
|
||||
} // 背景居中
|
||||
|
||||
this.$nextTick(async() => {
|
||||
this.$nextTick(async () => {
|
||||
ctx = document.getElementById('canvas').getContext('2d') // 获取上下文
|
||||
await ctx.drawImage(img, 0, 0, img.width, img.height) // 在canvas中绘制图片(图片、起始位置、绘图尺寸)
|
||||
this.drawToArr()
|
||||
@@ -512,6 +506,11 @@ export default {
|
||||
this.canvasData.push(this.currentDrawData) // 添加当前绘图数据
|
||||
}
|
||||
}
|
||||
// 向主窗体发送测量数据
|
||||
if (this.model) {
|
||||
var data = { type: 'setMeasurement', data: this.currentDrawData }
|
||||
window.opener.postMessage(data, window.location)
|
||||
}
|
||||
this.isMouseDown = false // 关闭鼠标状态
|
||||
this.model = ''
|
||||
this.lesionName = ''
|
||||
@@ -519,9 +518,6 @@ export default {
|
||||
x: e.offsetX, // 更新位置
|
||||
y: e.offsetY
|
||||
}
|
||||
// 向主窗体发送测量数据
|
||||
var data = { type: 'setMeasurement', data: this.currentDrawData }
|
||||
window.opener.postMessage(data, window.location)
|
||||
},
|
||||
|
||||
// 画标注
|
||||
@@ -773,42 +769,43 @@ export default {
|
||||
}
|
||||
</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:.8;
|
||||
cursor:pointer;
|
||||
box-sizing:border-box;
|
||||
user-select:none
|
||||
.image-viewer__wrapper {
|
||||
position: relative;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.image-viewer__close{
|
||||
.image-viewer__btn {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
opacity: .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
|
||||
top: 40px;
|
||||
right: 40px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
font-size: 40px
|
||||
}
|
||||
.image-viewer_desc{
|
||||
position:absolute;
|
||||
top:40px;
|
||||
left:40px;
|
||||
font-size:15px;
|
||||
|
||||
.image-viewer_desc {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
left: 40px;
|
||||
font-size: 15px;
|
||||
padding: 5px;
|
||||
height: 30px;
|
||||
width: 70px;
|
||||
@@ -821,92 +818,104 @@ export default {
|
||||
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:.5;
|
||||
// background:#000
|
||||
|
||||
}
|
||||
.viewer-fade-enter-active{
|
||||
animation:viewer-fade-in .3s
|
||||
}
|
||||
.viewer-fade-leave-active{
|
||||
animation:viewer-fade-out .3s
|
||||
.image-viewer__canvas {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center
|
||||
}
|
||||
|
||||
@keyframes viewer-fade-in{
|
||||
0%{
|
||||
transform:translate3d(0,-20px,0);
|
||||
opacity:0
|
||||
}
|
||||
100%{
|
||||
transform:translate3d(0,0,0);
|
||||
opacity:1
|
||||
}
|
||||
.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
|
||||
}
|
||||
|
||||
@keyframes viewer-fade-out{
|
||||
0%{
|
||||
transform:translate3d(0,0,0);
|
||||
opacity:1
|
||||
}
|
||||
100%{
|
||||
transform:translate3d(0,-20px,0);
|
||||
opacity:0
|
||||
}
|
||||
.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: .5;
|
||||
// background:#000
|
||||
|
||||
}
|
||||
|
||||
.viewer-fade-enter-active {
|
||||
animation: viewer-fade-in .3s
|
||||
}
|
||||
|
||||
.viewer-fade-leave-active {
|
||||
animation: viewer-fade-out .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>
|
||||
|
||||
@@ -3,61 +3,33 @@
|
||||
|
||||
<div class="image-viewer-wrapper">
|
||||
<!-- 预览图像 -->
|
||||
<NoneDicomsCanvas
|
||||
v-if="previewVisible"
|
||||
:on-switch="
|
||||
(index) => {
|
||||
selected(index)
|
||||
}
|
||||
"
|
||||
:initial-index="previewImage.index"
|
||||
:url-list="previewImage.imgList"
|
||||
:study-code="previewImage.studyCode"
|
||||
:body-part="previewImage.bodyPart"
|
||||
:modality="previewImage.modality"
|
||||
:study-id="previewImage.studyId"
|
||||
:reading-task-state="readingTaskState"
|
||||
/>
|
||||
<NoneDicomsCanvas v-if="previewVisible" :on-switch="(index) => {
|
||||
selected(index)
|
||||
}
|
||||
" :initial-index="previewImage.index" :url-list="previewImage.imgList" :study-code="previewImage.studyCode"
|
||||
:body-part="previewImage.bodyPart" :modality="previewImage.modality" :study-id="previewImage.studyId"
|
||||
:reading-task-state="readingTaskState" />
|
||||
</div>
|
||||
<div class="thumbnail-wrapper" style="z-index:999;background-color:#fff;">
|
||||
<div class="">
|
||||
<div class="img-wrapper">
|
||||
<el-button
|
||||
icon="el-icon-d-arrow-left"
|
||||
plain
|
||||
class="left to"
|
||||
:disabled="disabledPrev"
|
||||
@click="toRight"
|
||||
/>
|
||||
<el-button icon="el-icon-d-arrow-left" plain class="left to" :disabled="disabledPrev" @click="toRight" />
|
||||
<div ref="imagesWrapper" class="images">
|
||||
<div v-if="noData" class="empty-text">
|
||||
<slot name="empty">{{ $t('trial:reading:noneDicoms:noData') }}</slot>
|
||||
</div>
|
||||
<div v-show="!noData" class="items" :style="itemsStyle">
|
||||
<div
|
||||
v-for="(item, index) in previewImage.imgList"
|
||||
:key="index"
|
||||
class="item-img"
|
||||
:style="imgSize"
|
||||
:class="{
|
||||
'is-active': index === currentIndex
|
||||
}"
|
||||
@click="selected(index)"
|
||||
>
|
||||
<div v-for="(item, index) in previewImage.imgList" :key="index" class="item-img" :style="imgSize" :class="{
|
||||
'is-active': item.Id === currentFileId
|
||||
}" @click="selected(item.Id)">
|
||||
<img :title="item.FileName" :src="`${OSSclientConfig.basePath + item.Path}`" crossorigin="anonymous">
|
||||
<p v-if="item.FileName" class="item-date">
|
||||
{{ `${index+1}` }}
|
||||
{{ `${index + 1}` }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<el-button
|
||||
icon="el-icon-d-arrow-right"
|
||||
:disabled="disabledNext"
|
||||
plain
|
||||
class="right to"
|
||||
@click="Left"
|
||||
/>
|
||||
<el-button icon="el-icon-d-arrow-right" :disabled="disabledNext" plain class="right to" @click="Left" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -88,6 +60,10 @@ export default {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
currentFileId: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
previewImage: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
@@ -161,9 +137,9 @@ export default {
|
||||
this.pageSize = this.wrapperWidth() / this.itemWidth
|
||||
this.urlList = this.previewImage
|
||||
const scope = this
|
||||
window.onresize = function() {
|
||||
window.onresize = function () {
|
||||
scope.pageSize = scope.wrapperWidth() / scope.itemWidth
|
||||
scope.selected(scope.currentIndex)
|
||||
scope.selected(scope.currentFileId)
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -181,7 +157,8 @@ export default {
|
||||
this.translateX = maxTrans
|
||||
}
|
||||
},
|
||||
selected(index) {
|
||||
selected(id) {
|
||||
let index = this.previewImage.imgList.findIndex(item => item.Id === id)
|
||||
const center = this.pageSize >> 1
|
||||
// 最后一页的中间位置
|
||||
const lastCenter = this.dataLength - center
|
||||
@@ -198,7 +175,7 @@ export default {
|
||||
if (this.currentIndex !== index) {
|
||||
this.currentIndex = index
|
||||
}
|
||||
this.$emit('selectedImg', index)
|
||||
this.$emit('selectedImg', id)
|
||||
},
|
||||
wrapperWidth() {
|
||||
if (this.$refs.imagesWrapper) {
|
||||
@@ -212,35 +189,40 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.preview-wrapper{
|
||||
.preview-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.image-viewer-wrapper{
|
||||
.image-viewer-wrapper {
|
||||
flex: 1;
|
||||
}
|
||||
.thumbnail-wrapper{
|
||||
|
||||
.thumbnail-wrapper {
|
||||
height: 130px;
|
||||
}
|
||||
.img-content{
|
||||
|
||||
.img-content {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 10px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.img-wrapper {
|
||||
display: flex;
|
||||
position: relative;
|
||||
margin: 0 20px;
|
||||
height: 120px;
|
||||
|
||||
.to {
|
||||
width: 32px;
|
||||
height: 100%;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.images::before {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
@@ -249,16 +231,15 @@ export default {
|
||||
width: 84px;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
left top,
|
||||
right top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0))
|
||||
);
|
||||
background: -webkit-gradient(linear,
|
||||
left top,
|
||||
right top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0)));
|
||||
background: -o-linear-gradient(left, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
background: linear-gradient(90deg, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
}
|
||||
|
||||
.images::after {
|
||||
position: absolute;
|
||||
z-index: 5;
|
||||
@@ -268,22 +249,22 @@ export default {
|
||||
width: 84px;
|
||||
content: '';
|
||||
pointer-events: none;
|
||||
background: -webkit-gradient(
|
||||
linear,
|
||||
right top,
|
||||
left top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0))
|
||||
);
|
||||
background: -webkit-gradient(linear,
|
||||
right top,
|
||||
left top,
|
||||
from(#fff),
|
||||
color-stop(50%, rgba(0, 0, 0, 0)));
|
||||
background: -o-linear-gradient(right, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
background: linear-gradient(270deg, #fff, rgba(0, 0, 0, 0) 50%);
|
||||
}
|
||||
|
||||
.images {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
margin: 0 2px;
|
||||
|
||||
.empty-text {
|
||||
color: rgb(158, 158, 158);
|
||||
height: 100%;
|
||||
@@ -291,6 +272,7 @@ export default {
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.items {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -300,6 +282,7 @@ export default {
|
||||
height: 100%;
|
||||
align-items: center;
|
||||
transition: transform 0.25s ease;
|
||||
|
||||
.item-img {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
@@ -307,6 +290,7 @@ export default {
|
||||
margin-right: 8px;
|
||||
border: 2px solid rgba(0, 0, 0, 0);
|
||||
cursor: pointer;
|
||||
|
||||
.item-date {
|
||||
bottom: 0px;
|
||||
position: absolute;
|
||||
@@ -317,15 +301,18 @@ export default {
|
||||
line-height: 24px;
|
||||
color: white;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.item-img:hover::after {
|
||||
// border-color: #409EFF;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.item-img::after {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@@ -340,9 +327,11 @@ export default {
|
||||
transition: opacity 0.3s ease;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
.is-active {
|
||||
border-color: #409eff;
|
||||
}
|
||||
|
||||
.is-active:after {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
@@ -37,7 +37,8 @@
|
||||
<div class="add-icon" @click.prevent="downloadTpl(item.LesionType)">
|
||||
<i class="el-icon-download" />
|
||||
</div>
|
||||
<div class="add-icon" style="margin: 0 5px;" @click.prevent="uploadTpl(item.LesionType)">
|
||||
<div class="add-icon" style="margin: 0 5px;"
|
||||
@click.prevent="uploadTpl(item.LesionType, item.QuestionName)">
|
||||
<i class="el-icon-upload2" />
|
||||
</div>
|
||||
<div class="add-icon" @click.prevent="handleAddOrEdit('add', item)">
|
||||
@@ -64,7 +65,11 @@
|
||||
{{ `${scope.row[q.Id]} ${$fd('ValueUnit', parseInt(q.Unit))}` }}
|
||||
</span>
|
||||
<span v-else-if="q.DictionaryCode">
|
||||
{{ `${$fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}` }}
|
||||
{{`${scope.row[q.Id] instanceof Array ? scope.row[q.Id].map(item => $fd(q.DictionaryCode,
|
||||
parseInt(item))).join(',') : $fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}`}}
|
||||
</span>
|
||||
<span v-else-if="q.OptionTypeEnum === 1">
|
||||
{{ `${scope.row[q.Id] instanceof Array ? scope.row[q.Id].join(',') : scope.row[q.Id]}` }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ `${scope.row[q.Id]}` }}
|
||||
@@ -102,7 +107,7 @@
|
||||
</template>
|
||||
<template v-if="item.Type === 'select'">
|
||||
<el-select v-model="questionForm[item.Id]" :disabled="!isCurrentTask || readingTaskState >= 2"
|
||||
@change="((val) => { formItemChange(val, item) })">
|
||||
:multiple="item.OptionTypeEnum === 1" @change="((val) => { formItemChange(val, item) })">
|
||||
<el-option v-for="dict of $d[item.DictionaryCode]" :key="dict.id" :value="String(dict.value)"
|
||||
:label="dict.label" />
|
||||
</el-select>
|
||||
@@ -111,10 +116,10 @@
|
||||
<template v-if="item.Childrens && item.Childrens.length > 0">
|
||||
<template v-for="child in item.Childrens">
|
||||
<el-form-item :key="child.Id"
|
||||
v-if="(child.ShowQuestion === 1 && child.ParentTriggerValueList.includes(String(questionForm[item.Id]))) || child.ShowQuestion === 0"
|
||||
v-if="(child.ShowQuestion === 1 && (child.ParentTriggerValueList.includes(String(questionForm[item.Id])) || (Array.isArray(questionForm[item.Id]) && child.ParentTriggerValueList.some(da => questionForm[item.Id].includes(da))))) || child.ShowQuestion === 0"
|
||||
:label="`${child.QuestionName}`" :prop="child.Id" :rules="[
|
||||
{
|
||||
required: (child.IsRequired === 0 || (child.IsRequired === 1 && child.RelevanceId && (child.RelevanceValue.includes(questionForm[child.RelevanceId])))) && child.Type !== 'group' && child.Type !== 'summary',
|
||||
required: (child.IsRequired === 0 || (child.IsRequired === 1 && child.RelevanceId && ((child.RelevanceValue.includes(questionForm[child.RelevanceId])) || (Array.isArray(questionForm[child.RelevanceId]) && child.RelevanceValueList.some(da => questionForm[child.RelevanceId].includes(da)))))) && child.Type !== 'group' && child.Type !== 'summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(child.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']
|
||||
},
|
||||
]">
|
||||
@@ -152,8 +157,8 @@
|
||||
<el-dialog v-if="addOrEdit.visible" :visible.sync="addOrEdit.visible" :close-on-click-modal="false"
|
||||
:title="addOrEdit.title" width="500px">
|
||||
<el-form ref="tableQsForm" v-loading="loading" :model="qsForm" size="small">
|
||||
<QuestionTableFormItem v-for="item in qsList" :key="item.Id" :question="item" :question-form="qsForm"
|
||||
:reading-task-state="readingTaskState" @setFormItemData="setFormItemData"
|
||||
<QuestionTableFormItem v-for="item in qsList" :key="item.Id" :question="item" :questions="qsList"
|
||||
:question-form="qsForm" :reading-task-state="readingTaskState" @setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData" />
|
||||
<el-form-item style="text-align: right">
|
||||
<el-button size="small" @click="addOrEdit.visible = false">
|
||||
@@ -169,7 +174,8 @@
|
||||
<!-- 导入 -->
|
||||
<el-dialog v-if="upload.visible" :visible.sync="upload.visible" :close-on-click-modal="false"
|
||||
:title="upload.title" width="500px">
|
||||
<UploadExcel :visit-task-id="visitTaskId" :lesion-type="upload.lesionType" @close="uploadDlgClose" />
|
||||
<UploadExcel :visit-task-id="visitTaskId" :lesion-type="upload.lesionType" :TableName="upload.TableName"
|
||||
@close="uploadDlgClose" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
@@ -228,7 +234,7 @@ export default {
|
||||
formChanged: false,
|
||||
digitPlaces: 2,
|
||||
addOrEdit: { visible: false, title: '', lesionType: null },
|
||||
upload: { visible: false, title: '', lesionType: null },
|
||||
upload: { visible: false, title: '', lesionType: null, TableName: '', },
|
||||
qsList: [],
|
||||
answersList: [],
|
||||
qsForm: {},
|
||||
@@ -319,7 +325,7 @@ export default {
|
||||
const type = ['number', 'radio', 'select', 'input', 'textarea', 'calculation']
|
||||
questions.forEach(item => {
|
||||
if (type.includes(item.Type)) {
|
||||
const answer = item.Type === 'number' || item.Type === 'calculation' ? isNaN(parseFloat(item.Answer)) ? null : parseFloat(item.Answer) : item.Answer
|
||||
const answer = item.Type === 'select' && item.OptionTypeEnum === 1 && item.Answer ? JSON.parse(item.Answer) : item.Type === 'number' || item.Type === 'calculation' ? isNaN(parseFloat(item.Answer)) ? null : parseFloat(item.Answer) : item.Answer
|
||||
this.$set(this.questionForm, item.Id, answer)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
@@ -476,7 +482,7 @@ export default {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
answers.push({ id: k, answer: Array.isArray(this.questionForm[k]) ? JSON.stringify(this.questionForm[k]) : this.questionForm[k] })
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
@@ -604,7 +610,7 @@ export default {
|
||||
for (const k in this.qsForm) {
|
||||
if (reg.test(k)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
|
||||
answers.push({ tableQuestionId: k, answer: this.qsForm[k] })
|
||||
answers.push({ tableQuestionId: k, answer: Array.isArray(this.qsForm[k]) ? JSON.stringify(this.qsForm[k]) : this.qsForm[k] })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -669,8 +675,9 @@ export default {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
uploadTpl(lesionType) {
|
||||
uploadTpl(lesionType, TableName) {
|
||||
this.upload.lesionType = lesionType
|
||||
this.upload.TableName = TableName
|
||||
this.upload.title = `导入( ${this.$fd('LesionType', lesionType)} )`
|
||||
this.upload.visible = true
|
||||
},
|
||||
|
||||
+79
-122
@@ -1,119 +1,66 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<div v-if="!!question.GroupName && question.Type === 'group'">
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
{{ 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']},
|
||||
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' : '']"
|
||||
>
|
||||
: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-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-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]"
|
||||
<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)})"
|
||||
>
|
||||
clearable :multiple="question.OptionTypeEnum === 1" @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]"
|
||||
/>
|
||||
<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"
|
||||
/>
|
||||
<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
|
||||
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"
|
||||
/>
|
||||
<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)})"
|
||||
>
|
||||
<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)"
|
||||
>
|
||||
<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"
|
||||
>
|
||||
<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"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
<el-checkbox-group v-else-if="question.Type === 'checkbox'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2" @change="((val) => { formItemChange(val, question) })">
|
||||
<el-checkbox v-for="val in question.TypeValue.split('|')" :key="val" :label="val">
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
@@ -144,24 +91,15 @@
|
||||
/>
|
||||
</template> -->
|
||||
<!-- 数值类型 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='number'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState>=2 "
|
||||
type="number"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-input v-else-if="question.Type === 'number'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2" type="number" @change="((val) => { formItemChange(val, question) })">
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-input v-else-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled
|
||||
@change="((val) => { formItemChange(val, question) })">
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
@@ -169,15 +107,9 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<QuestionTableFormItem
|
||||
v-for="item in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
<QuestionTableFormItem v-for="item in question.Childrens" :key="item.Id" :question="item" :questions="questions"
|
||||
:question-form="questionForm" :reading-task-state="readingTaskState" @setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -197,6 +129,12 @@ export default {
|
||||
return []
|
||||
}
|
||||
},
|
||||
questions: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
@@ -223,6 +161,7 @@ export default {
|
||||
}
|
||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
||||
}
|
||||
this.resetChildValue(question, this.questions)
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
@@ -232,6 +171,17 @@ export default {
|
||||
}
|
||||
})
|
||||
},
|
||||
resetChildValue(obj, arr) {
|
||||
arr.some(item => {
|
||||
if (item.ParentId === obj.Id) {
|
||||
this.$emit('resetFormItemData', item.Id)
|
||||
}
|
||||
if (item.Childrens && item.Childrens.length > 0) {
|
||||
this.resetChildValue(obj, item.Childrens)
|
||||
}
|
||||
return item.ParentId === obj.Id
|
||||
})
|
||||
},
|
||||
limitBlur(valueType, value) {
|
||||
if (isNaN(parseInt(value))) {
|
||||
value = null
|
||||
@@ -269,29 +219,36 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
.mb {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
|
||||
.disabled {
|
||||
::v-deep .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
|
||||
.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-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;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadOCTFCTTemplate, uploadOCTLipidAngleTemplate } from '@/api/reading'
|
||||
import { readingImport } from '@/api/reading'
|
||||
export default {
|
||||
props: {
|
||||
visitTaskId: {
|
||||
@@ -43,6 +43,10 @@ export default {
|
||||
lesionType: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
TableName: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -67,10 +71,13 @@ export default {
|
||||
var data = new FormData()
|
||||
data.append('file', param.file)
|
||||
data.append('visitTaskId', this.visitTaskId)
|
||||
data.append('TableName', this.TableName)
|
||||
if (this.lesionType === 112) {
|
||||
await uploadOCTFCTTemplate(data)
|
||||
data.append('readingImportType', 1)
|
||||
await readingImport(data)
|
||||
} else {
|
||||
await uploadOCTLipidAngleTemplate(data)
|
||||
data.append('readingImportType', 2)
|
||||
await readingImport(data)
|
||||
}
|
||||
this.$emit('close')
|
||||
this.$message.success('导入成功!')
|
||||
|
||||
@@ -364,6 +364,15 @@ export default {
|
||||
this.lesionName = this.getLesionInfo(this.orderMark, this.rowIndex)
|
||||
this.isCurrentTaskAdd = this.answers.IsCurrentTaskAdd ? this.answers.IsCurrentTaskAdd : 'True'
|
||||
this.lesionMark = this.getLesionName(this.orderMark, this.questionForm.RowIndex)
|
||||
|
||||
var isLymphLesion = this.getQuestionVal(2)
|
||||
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
|
||||
var lesionOrgan = this.getQuestionVal(6)
|
||||
const lesionPart = this.getQuestionVal(8)
|
||||
|
||||
this.$emit('resetQuestions', { isLymphLesion, lesionPart, lesionOrgan, saveTypeEnum: this.questionForm.saveTypeEnum, lesionState, lesionNum, rowIndex: this.rowIndex, questionId: this.parentQsId, anwsers: this.questionForm })
|
||||
|
||||
|
||||
this.isRender = true
|
||||
},
|
||||
getLesionName(orderMark, rowIndex) {
|
||||
@@ -590,7 +599,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -6,47 +6,53 @@
|
||||
>
|
||||
{{ question.GroupName }}
|
||||
</div> -->
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<div v-if="!!question.GroupName && question.Type === 'group'">
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
{{ language === 'en' ? question.GroupEnName : question.GroupName }}
|
||||
</h4>
|
||||
</div>
|
||||
<template v-else-if="((question.QuestionType === 56 || question.QuestionType === 57) && question.IsBaseLineTask)" />
|
||||
<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']},
|
||||
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' : '']"
|
||||
>
|
||||
:class="[question.Type === 'group' ? 'mb' : (question.Type === 'upload' || question.QuestionName.length > 15) ? 'uploadWrapper' : '']">
|
||||
<template v-if="question.QuestionType === 60 || question.QuestionType === 61">
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
|
||||
|
||||
<el-input
|
||||
v-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
style="width: 130px;"
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
<div style="display: flex;justify-content: space-between;" v-if="question.Type === 'calculation'">
|
||||
<el-input v-if="question.Type === 'calculation'" v-model="questionForm[question.Id]" disabled
|
||||
style="width: 130px;">
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart"
|
||||
class="svg-icon svg-readingChart" @click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
QuestionId: question.Id,
|
||||
QuestionName: question.QuestionName
|
||||
}
|
||||
})" />
|
||||
</div>
|
||||
<!-- 测量 -->
|
||||
<el-button v-if="!questionForm[question.Id] && readingTaskState!== 2" size="mini" type="text" @click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation') }}</el-button>
|
||||
<el-button v-if="!questionForm[question.Id] && readingTaskState !== 2" size="mini" type="text"
|
||||
@click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation') }}</el-button>
|
||||
<!-- 清除标记 -->
|
||||
<el-button v-if="questionForm[question.Id]&& readingTaskState!== 2" size="mini" type="text" @click="removeAnnotation(question)">{{ $t('trials:lugano:button:clearAnnotation') }}</el-button>
|
||||
<el-button v-if="questionForm[question.Id] && readingTaskState !== 2" size="mini" type="text"
|
||||
@click="removeAnnotation(question)">{{ $t('trials:lugano:button:clearAnnotation') }}</el-button>
|
||||
<!-- 定位 -->
|
||||
<el-button v-if="questionForm[question.Id]" size="mini" type="text" @click="locateAnnotation(question)">{{ $t('trials:lugano:button:locateAnnotation') }}</el-button>
|
||||
<el-button v-if="questionForm[question.Id]" size="mini" type="text" @click="locateAnnotation(question)">{{
|
||||
$t('trials:lugano:button:locateAnnotation') }}</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button v-if="readingTaskState!== 2 && question.SaveEnum === 1" size="mini" type="text" @click="saveAnnotation(question)">
|
||||
<el-button v-if="readingTaskState !== 2 && question.SaveEnum === 1" size="mini" type="text"
|
||||
@click="saveAnnotation(question)">
|
||||
<!-- 未保存 -->
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
|
||||
<i class="el-icon-warning" style="color:red" />
|
||||
@@ -56,157 +62,100 @@
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-else-if="question.QuestionType === 48 || question.QuestionType === 51 || question.QuestionType === 52 || question.QuestionType === 53">
|
||||
<el-input
|
||||
v-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>
|
||||
<template
|
||||
v-else-if="question.QuestionType === 48 || question.QuestionType === 51 || question.QuestionType === 52 || question.QuestionType === 53">
|
||||
<div style="display: flex;justify-content: space-between;" v-if="question.Type === 'calculation'">
|
||||
<el-input v-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>
|
||||
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
|
||||
@click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
QuestionId: question.Id,
|
||||
QuestionName: question.QuestionName
|
||||
}
|
||||
})" />
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<el-input v-else-if="question.Type === 'input'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask" @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 || isFirstChangeTask"
|
||||
@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 || isFirstChangeTask"
|
||||
@change="((val) => { formItemChange(val, question) })" />
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-else-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
<el-select v-else-if="question.Type === 'select'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode) || isFirstChangeTask || question.QuestionType === 50 || question.QuestionType === 55"
|
||||
clearable
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
clearable :multiple="question.OptionTypeEnum === 1" @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]"
|
||||
/>
|
||||
<el-option v-for="item in organList" :key="item.Id" :label="item[question.DataTableColumn]"
|
||||
:value="item[question.DataTableColumn]" />
|
||||
</template>
|
||||
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 47 && question.IsBaseLineTask">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 ||item.value === 2 || item.value === 5 "
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
<el-option v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 || item.value === 2 || item.value === 5" :key="item.id"
|
||||
:value="String(item.value)" :label="item.label" />
|
||||
</template>
|
||||
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 47 && !question.IsBaseLineTask">
|
||||
<template
|
||||
v-else-if="question.QuestionGenre === 3 && question.QuestionType === 47 && !question.IsBaseLineTask">
|
||||
<el-option-group
|
||||
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 ||item.value === 3|| item.value === 4 || item.value === 5"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode, parseFloat(question.LastTaskAnswer))}` : ''">
|
||||
<el-option v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 || item.value === 3 || item.value === 4 || item.value === 5" :key="item.id"
|
||||
:value="String(item.value)" :label="item.label" />
|
||||
</el-option-group>
|
||||
</template>
|
||||
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 49 && question.IsBaseLineTask">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 ||item.value === 5 || item.value === 6 "
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
<el-option v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 || item.value === 5 || item.value === 6" :key="item.id"
|
||||
:value="String(item.value)" :label="item.label" />
|
||||
</template>
|
||||
<template v-else-if="question.QuestionGenre === 3 && question.QuestionType === 49 && !question.IsBaseLineTask">
|
||||
<template
|
||||
v-else-if="question.QuestionGenre === 3 && question.QuestionType === 49 && !question.IsBaseLineTask">
|
||||
<el-option-group
|
||||
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 ||item.value === 2 || item.value === 3 || item.value === 4 || item.value === 5"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode, parseFloat(question.LastTaskAnswer))}` : ''">
|
||||
<el-option v-for="item of $d[question.DictionaryCode]"
|
||||
v-show="item.value === 1 || item.value === 2 || item.value === 3 || item.value === 4 || item.value === 5"
|
||||
:key="item.id" :value="String(item.value)" :label="item.label" />
|
||||
</el-option-group>
|
||||
</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"
|
||||
/>
|
||||
<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
|
||||
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"
|
||||
/>
|
||||
<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 || isFirstChangeTask"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-radio-group v-else-if="question.Type === 'radio'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask" @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)"
|
||||
>
|
||||
<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"
|
||||
>
|
||||
<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 || isFirstChangeTask"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
<el-checkbox-group v-else-if="question.Type === 'checkbox'" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask">
|
||||
<el-checkbox v-for="val in question.TypeValue.split('|')" :key="val" :label="val">
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
@@ -217,80 +166,52 @@
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
:precision="2"
|
||||
/> -->
|
||||
<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 || isFirstChangeTask"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
/>
|
||||
</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)) }}
|
||||
<div style="display: flex;justify-content: space-between;"
|
||||
v-else-if="question.Type === 'number' || question.Type === 'calculation'">
|
||||
<template v-if="question.Type === 'number'">
|
||||
<el-input-number v-if="question.ValueType === 0" v-model="questionForm[question.Id]" :precision="0"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask" />
|
||||
<el-input-number v-else-if="question.ValueType === 3" v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask" />
|
||||
<el-input-number v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]" :precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask" />
|
||||
</template>
|
||||
</el-input>
|
||||
<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>
|
||||
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
|
||||
@click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
QuestionId: question.Id,
|
||||
QuestionName: question.QuestionName
|
||||
}
|
||||
})" />
|
||||
</div>
|
||||
<!-- 上传图像 -->
|
||||
<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 || isFirstChangeTask"
|
||||
>
|
||||
<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 || isFirstChangeTask">
|
||||
<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=""
|
||||
>
|
||||
<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)"
|
||||
>
|
||||
<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)"
|
||||
>
|
||||
<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-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>
|
||||
@@ -300,17 +221,9 @@
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<QuestionItem
|
||||
v-for="(item) in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:reading-task-state="readingTaskState"
|
||||
:is-first-change-task="isFirstChangeTask"
|
||||
:question-form="questionForm"
|
||||
:visit-task-id="visitTaskId"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
<QuestionItem v-for="(item) in question.Childrens" :key="item.Id" :question="item"
|
||||
:reading-task-state="readingTaskState" :is-first-change-task="isFirstChangeTask" :question-form="questionForm"
|
||||
:visit-task-id="visitTaskId" @setFormItemData="setFormItemData" @resetFormItemData="resetFormItemData" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -423,7 +336,7 @@ export default {
|
||||
.then(() => {
|
||||
DicomEvent.$emit('removeAnnotation', question)
|
||||
})
|
||||
.catch(() => {})
|
||||
.catch(() => { })
|
||||
},
|
||||
locateAnnotation(question) {
|
||||
DicomEvent.$emit('locateAnnotation', question)
|
||||
@@ -479,29 +392,36 @@ export default {
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
.mb {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
|
||||
.disabled {
|
||||
::v-deep .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
|
||||
.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-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;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
:visit-task-id="visitTaskId"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
@handleReadingChart="handleReadingChart"
|
||||
/>
|
||||
|
||||
<el-form-item v-if="readingTaskState < 2 && !isFirstChangeTask">
|
||||
@@ -150,6 +151,9 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleReadingChart(e) {
|
||||
this.$emit('handleReadingChart', e)
|
||||
},
|
||||
async getQuestions(visitTaskId, isRefresh = false) {
|
||||
var isChangeVisitTask = this.visitTaskId !== visitTaskId
|
||||
this.visitTaskId = visitTaskId
|
||||
@@ -452,7 +456,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -7,14 +7,10 @@
|
||||
<div class="visit-name-wrapper">
|
||||
|
||||
<div v-if="(visitTaskList.length > 0)" style="display: flex;flex-direction: row;">
|
||||
<div
|
||||
v-for="s in visitTaskList"
|
||||
:key="s.VisitTaskId"
|
||||
class="visit-item"
|
||||
:class="{'visit-item-active': activeTaskVisitId==s.VisitTaskId}"
|
||||
|
||||
@click.prevent="handleClick(s)"
|
||||
>{{ s.TaskBlindName }}</div>
|
||||
<div v-for="s in visitTaskList" :key="s.VisitTaskId" class="visit-item"
|
||||
:class="{ 'visit-item-active': activeTaskVisitId == s.VisitTaskId }" @click.prevent="handleClick(s)">
|
||||
{{
|
||||
s.TaskBlindName }}</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -22,23 +18,12 @@
|
||||
|
||||
</div>
|
||||
<div class="right">
|
||||
<div
|
||||
v-for="s in visitTaskList"
|
||||
v-show="activeTaskVisitId === s.VisitTaskId"
|
||||
:key="s.VisitTaskId"
|
||||
class="study-wrapper"
|
||||
>
|
||||
<StudyList
|
||||
v-if="selectArr.includes(s.VisitTaskId)"
|
||||
:ref="s.VisitTaskId"
|
||||
:visit-task-id="s.VisitTaskId"
|
||||
:trial-id="trialId"
|
||||
:subject-visit-id="s.VisitId"
|
||||
:task-blind-name="s.TaskBlindName"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
@loadImageStack="loadImageStack"
|
||||
@previewNoneDicoms="previewNoneDicoms"
|
||||
/>
|
||||
<div v-for="s in visitTaskList" v-show="activeTaskVisitId === s.VisitTaskId" :key="s.VisitTaskId"
|
||||
class="study-wrapper">
|
||||
<StudyList v-if="selectArr.includes(s.VisitTaskId)" :ref="s.VisitTaskId" :visit-task-id="s.VisitTaskId"
|
||||
:trial-id="trialId" :subject-visit-id="s.VisitId" :task-blind-name="s.TaskBlindName"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo" @loadImageStack="loadImageStack"
|
||||
@previewNoneDicoms="previewNoneDicoms" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -46,23 +31,17 @@
|
||||
</div>
|
||||
<div class="dicom-viewer">
|
||||
<div class="container">
|
||||
<DicomViewer
|
||||
v-if="activeTaskVisitId"
|
||||
ref="dicomViewer"
|
||||
:is-show="isShow"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
:is-exists-no-dicom-file="isExistsNoDicomFile"
|
||||
<DicomViewer v-if="activeTaskVisitId" ref="dicomViewer" :is-show="isShow"
|
||||
:question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum"
|
||||
:is-exists-clinical-data="isExistsClinicalData" :is-exists-no-dicom-file="isExistsNoDicomFile"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
:is-exists-manual="isExistsManual"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||
@previewCD="previewCD"
|
||||
/>
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder" :is-exists-manual="isExistsManual"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading" @previewCD="previewCD"
|
||||
@handleReadingChart="handleReadingChart" />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<readingChart ref="readingChart" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -75,7 +54,9 @@ import { getToken } from '@/utils/auth'
|
||||
import { mapGetters } from 'vuex'
|
||||
import * as dicomParser from 'dicom-parser'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import { workSpeedclose } from "@/utils"
|
||||
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
import readingChart from '@/components/readingChart'
|
||||
// import metaDataProvider from '@/utils/metaDataProvider'
|
||||
// cornerstone.metaData.addProvider(metaDataProvider, { priority: 10 });
|
||||
var config = {
|
||||
@@ -96,7 +77,8 @@ export default {
|
||||
name: 'ReadPage',
|
||||
components: {
|
||||
DicomViewer,
|
||||
StudyList
|
||||
StudyList,
|
||||
readingChart
|
||||
},
|
||||
props: {
|
||||
trialId: {
|
||||
@@ -238,6 +220,7 @@ export default {
|
||||
window.addEventListener('beforeunload', e => {
|
||||
cornerstone.imageCache.purgeCache()
|
||||
})
|
||||
document.addEventListener("click", this.foo);
|
||||
},
|
||||
beforeDestroy() {
|
||||
cornerstone.imageCache.purgeCache()
|
||||
@@ -248,8 +231,24 @@ export default {
|
||||
DicomEvent.$off('addNoneDicomMeasureData')
|
||||
DicomEvent.$off('selectSeries')
|
||||
window.removeEventListener('beforeunload', e => { cornerstone.imageCache.purgeCache() })
|
||||
workSpeedclose(true)
|
||||
},
|
||||
methods: {
|
||||
handleReadingChart(row) {
|
||||
let { e, data } = row
|
||||
let obj = Object.assign({}, data)
|
||||
obj.TrialId = this.$route.query.trialId
|
||||
obj.VisitTaskId = this.visitTaskId
|
||||
let zIndex = 9
|
||||
if (obj.RowIndex) {
|
||||
zIndex = 9999
|
||||
}
|
||||
this.$refs.readingChart.init(e, obj, zIndex)
|
||||
},
|
||||
foo() {
|
||||
if (!this.$refs.readingChart) return false
|
||||
this.$refs.readingChart.foo()
|
||||
},
|
||||
async getVisitInfo() {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
|
||||
@@ -474,7 +473,7 @@ export default {
|
||||
getSeriesInfoByMark(baseSeries, visitTaskId, obj, visitTaskIdx) {
|
||||
var seriesInfo = null
|
||||
if (obj) {
|
||||
// 根据任务ID测量病灶信息
|
||||
// 根据任务ID测量病灶信息
|
||||
var index = visitTaskIdx
|
||||
if (index > -1) {
|
||||
var idx = -1
|
||||
@@ -497,7 +496,7 @@ export default {
|
||||
// var instanceIdx = series.instanceList.findIndex(imageId => !!~imageId.indexOf(instanceId))
|
||||
const frame = this.visitTaskList[index].MeasureData[idx].MeasureData.frame
|
||||
// const filterStr = series.isExistMutiFrames ? `frame=${frame}&instanceId=${instanceId}` : `instanceId=${instanceId}`
|
||||
let n = series.instanceInfoList.findIndex(k=>k.Id === instanceId)
|
||||
let n = series.instanceInfoList.findIndex(k => k.Id === instanceId)
|
||||
let filterStr = ''
|
||||
if (n > -1 && series.isExistMutiFrames) {
|
||||
if (series.instanceInfoList[n].NumberOfFrames > 0) {
|
||||
@@ -538,13 +537,15 @@ export default {
|
||||
params[key] = value
|
||||
}
|
||||
params.percentComplete = e.detail.percentComplete
|
||||
params.FileTotal = e.detail.total
|
||||
params.imageId = imageId
|
||||
store.dispatch('reading/setImageLoadedProgress', params)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.dicom-container{
|
||||
.dicom-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
@@ -553,32 +554,35 @@ export default {
|
||||
background-color: #000;
|
||||
box-sizing: border-box;
|
||||
user-select: none;
|
||||
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
|
||||
.dicom-viewer{
|
||||
.dicom-viewer {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
|
||||
.container{
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
}
|
||||
.dicom-list{
|
||||
width: 200px;
|
||||
padding: 5px 0px;
|
||||
|
||||
.dicom-list {
|
||||
width: 200px;
|
||||
padding: 5px 0px;
|
||||
box-sizing: border-box;
|
||||
|
||||
.container{
|
||||
.container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-sizing: border-box;
|
||||
@@ -586,7 +590,8 @@ export default {
|
||||
// border: 1px solid #ccc;
|
||||
|
||||
}
|
||||
::v-deep.el-tabs{
|
||||
|
||||
::v-deep.el-tabs {
|
||||
box-sizing: border-box;
|
||||
padding: 0 5px;
|
||||
height: 100%;
|
||||
@@ -594,26 +599,31 @@ export default {
|
||||
flex-direction: column;
|
||||
// justify-content: flex-start;
|
||||
border: 1px solid #727272;
|
||||
.el-tabs__item{
|
||||
|
||||
.el-tabs__item {
|
||||
color: #fff;
|
||||
}
|
||||
.el-tabs__header{
|
||||
|
||||
.el-tabs__header {
|
||||
height: 55px;
|
||||
margin:0px;
|
||||
margin: 0px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.el-tabs__content{
|
||||
|
||||
.el-tabs__content {
|
||||
flex: 1;
|
||||
margin:0px;
|
||||
margin: 0px;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.el-tabs__item{
|
||||
|
||||
.el-tabs__item {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
}
|
||||
.dicom-desc{
|
||||
|
||||
.dicom-desc {
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
text-align: center;
|
||||
@@ -621,23 +631,28 @@ export default {
|
||||
color: #d0d0d0;
|
||||
padding: 2px;
|
||||
}
|
||||
|
||||
.ps {
|
||||
overflow-anchor: none;
|
||||
touch-action: auto;
|
||||
}
|
||||
|
||||
.series-active {
|
||||
background-color: #607d8b!important;
|
||||
border: 1px solid #607d8b!important;
|
||||
background-color: #607d8b !important;
|
||||
border: 1px solid #607d8b !important;
|
||||
}
|
||||
::v-deep.el-progress__text{
|
||||
|
||||
::v-deep.el-progress__text {
|
||||
color: #ccc;
|
||||
font-size: 12px;
|
||||
}
|
||||
.series{
|
||||
|
||||
.series {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
|
||||
.series-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -650,11 +665,13 @@ export default {
|
||||
border-radius: 2px;
|
||||
border: 1px solid #404040;
|
||||
background-color: #3a3a3a;
|
||||
.el-progress__text{
|
||||
|
||||
.el-progress__text {
|
||||
display: none;
|
||||
}
|
||||
.el-progress-bar{
|
||||
padding-right:0px;
|
||||
|
||||
.el-progress-bar {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.image-preview {
|
||||
@@ -663,9 +680,11 @@ export default {
|
||||
border: 2px solid #252525;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.image-desc {
|
||||
vertical-align: top;
|
||||
p{
|
||||
|
||||
p {
|
||||
width: 100px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@@ -678,7 +697,8 @@ export default {
|
||||
}
|
||||
}
|
||||
}
|
||||
.related-study-wrapper{
|
||||
|
||||
.related-study-wrapper {
|
||||
box-sizing: border-box;
|
||||
height: 100%;
|
||||
padding-bottom: 5px;
|
||||
@@ -686,14 +706,15 @@ export default {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
.left{
|
||||
.left {
|
||||
position: relative;
|
||||
width: 25px;
|
||||
height: 100%;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
.visit-name-wrapper{
|
||||
|
||||
.visit-name-wrapper {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
|
||||
@@ -708,30 +729,34 @@ export default {
|
||||
// flex-direction: row;
|
||||
// align-content: flex-start;
|
||||
}
|
||||
.visit-item{
|
||||
|
||||
.visit-item {
|
||||
margin-left: 10px;
|
||||
white-space: nowrap;
|
||||
padding: 0px 4px;
|
||||
padding: 0px 4px;
|
||||
border: 1px solid #999999;
|
||||
border-bottom:none ;
|
||||
border-bottom: none;
|
||||
text-align: center;
|
||||
background-color: #4e4e4e;
|
||||
color: #d5d5d5;
|
||||
cursor: pointer;
|
||||
// margin-left: 10px;
|
||||
}
|
||||
.visit-item-active{
|
||||
|
||||
.visit-item-active {
|
||||
background-color: #607d8b;
|
||||
border: 1px solid #607d8b;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
width:170px;
|
||||
flex:1;
|
||||
|
||||
.right {
|
||||
width: 170px;
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
border-left: 1px solid #4a4a4a;
|
||||
color: #d5d5d5;
|
||||
.study-wrapper{
|
||||
|
||||
.study-wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -64,17 +64,28 @@
|
||||
|
||||
<!-- 输入框 -->
|
||||
<template v-if="qs.Type==='input' || qs.Type==='number'">
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<el-input
|
||||
v-if="qs.Type==='input' || qs.Type==='number'"
|
||||
v-model="questionForm[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) || !!answers.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answers.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answers.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>
|
||||
<svg-icon v-if="qs.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
|
||||
@click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
TableQuestionId: qs.Id,
|
||||
RowIndex: questionForm.RowIndex,
|
||||
QuestionName: qs.QuestionName
|
||||
}
|
||||
})" />
|
||||
</div>
|
||||
<!-- {{ ((qs.QuestionMark === 6 && isCurrentTaskAdd === 'False') || (qs.QuestionMark === 6 && isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition)) }} -->
|
||||
<el-input
|
||||
v-if="qs.Type==='input' || qs.Type==='number'"
|
||||
v-model="questionForm[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) || !!answers.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answers.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answers.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
|
||||
@@ -307,6 +318,9 @@ export default {
|
||||
DicomEvent.$off('handleImageQualityAbnormal')
|
||||
},
|
||||
methods: {
|
||||
handleReadingChart(e) {
|
||||
this.$emit('handleReadingChart', e)
|
||||
},
|
||||
async initForm() {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
this.questions.forEach(item => {
|
||||
@@ -801,7 +815,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
<!-- 非测量问题 -->
|
||||
<div class="lesions">
|
||||
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" />
|
||||
<Questions ref="ecrf" :question-form-change-state="questionFormChangeState" :question-form-change-num="questionFormChangeNum" @handleReadingChart="handleReadingChart"/>
|
||||
</div>
|
||||
<!-- 测量问题 -->
|
||||
<template v-if="questions.length > 0 && CriterionType !== 10">
|
||||
@@ -30,7 +30,16 @@
|
||||
<div class="lesion_list">
|
||||
<div v-for="item in qs.Childrens" v-show="!(isBaseLineTask && item.LesionType === 2)" :key="item.Id">
|
||||
<div v-if="item.Type === 'table'" class="flex-row" style="margin:3px 0;">
|
||||
<div class="title">{{ item.QuestionName }}</div>
|
||||
<div class="title">{{ item.QuestionName }}
|
||||
<svg-icon v-if="item.LesionType === 0" icon-class="readingChart"
|
||||
class="svg-icon svg-readingChart-mini" @click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
ReportChartTypeEnum: 0,
|
||||
QuestionName: item.QuestionName
|
||||
},
|
||||
})" />
|
||||
</div>
|
||||
<div v-if="readingTaskState<2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon" @click.prevent="handleAdd(item)">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
@@ -120,6 +129,7 @@
|
||||
@determineExistsUnsavedLession="determineExistsUnsavedLession"
|
||||
@resetQuestions="resetQuestions"
|
||||
@close="close"
|
||||
@handleReadingChart="handleReadingChart"
|
||||
/>
|
||||
</el-collapse-item>
|
||||
|
||||
@@ -240,6 +250,9 @@ export default {
|
||||
DicomEvent.$off('getUnSaveTarget')
|
||||
},
|
||||
methods: {
|
||||
handleReadingChart(e) {
|
||||
this.$emit('handleReadingChart', e)
|
||||
},
|
||||
async initList() {
|
||||
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId)
|
||||
if (i > -1) {
|
||||
|
||||
@@ -727,7 +727,7 @@ export default {
|
||||
file = this.convertBase64ToBlob(file)
|
||||
var trialId = this.$route.query.trialId
|
||||
var subjectId = this.$route.query.trialId
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
|
||||
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/${this.visitTaskId}/${fileName}.png`, file)
|
||||
return { isSuccess: true, result: result }
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
|
||||
@@ -69,7 +69,20 @@
|
||||
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-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 }}
|
||||
<svg-icon
|
||||
v-if="scope.row.ShowChartTypeEnum > 0 || (scope.row.LesionType === 0 && scope.row.ReportLayType === 1) || (scope.row.LesionType === 4 && scope.row.ReportLayType === 1)"
|
||||
icon-class="readingChart" class="svg-icon svg-readingChart-mini" @click.stop="(e) => handleReadingChart({
|
||||
e,
|
||||
data: {
|
||||
QuestionId: scope.row.RowIndex ? null : scope.row.QuestionId,
|
||||
TableQuestionId: scope.row.RowIndex ? scope.row.TableQuestionId : null,
|
||||
RowIndex: scope.row.RowIndex ? scope.row.RowIndex : null,
|
||||
ReportChartTypeEnum: (scope.row.LesionType === 0 && scope.row.ReportLayType === 1) ? 0 : (scope.row.LesionType === 4 && scope.row.ReportLayType === 1) ? 1 : null,
|
||||
QuestionName: scope.row.QuestionName
|
||||
}
|
||||
})" />
|
||||
</span>
|
||||
<span
|
||||
v-else
|
||||
style="font-weight: bold;font-size: 16px;color: #f44336;"
|
||||
@@ -266,6 +279,7 @@
|
||||
</div>
|
||||
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
<readingChart ref="readingChart_report" />
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -280,9 +294,10 @@ import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import AdditionalAssessment from './AdditionalAssessment'
|
||||
import readingChart from '@/components/readingChart'
|
||||
export default {
|
||||
name: 'ReportPage',
|
||||
components: { SignForm, AdditionalAssessment },
|
||||
components: { SignForm, AdditionalAssessment, readingChart },
|
||||
props: {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
@@ -352,6 +367,7 @@ export default {
|
||||
}
|
||||
})
|
||||
this.getReportInfo()
|
||||
document.addEventListener("click", this.foo);
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('getReportInfo')
|
||||
@@ -361,6 +377,22 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleReadingChart(row) {
|
||||
let { e, data } = row
|
||||
let obj = Object.assign({}, data)
|
||||
obj.TrialId = this.$route.query.trialId
|
||||
obj.VisitTaskId = this.visitTaskId
|
||||
obj.key = 'readingChart_report'
|
||||
let zIndex = 9
|
||||
if (obj.RowIndex) {
|
||||
zIndex = 9999
|
||||
}
|
||||
this.$refs.readingChart_report.init(e, obj, zIndex)
|
||||
},
|
||||
foo() {
|
||||
if (!this.$refs.readingChart_report) return false
|
||||
this.$refs.readingChart_report.foo()
|
||||
},
|
||||
myConfirm(msg) {
|
||||
return new Promise(resolve => {
|
||||
this.$confirm(msg, {
|
||||
|
||||
@@ -1,15 +1,7 @@
|
||||
<template>
|
||||
<div
|
||||
id="canvas"
|
||||
ref="canvas"
|
||||
v-loading="loading"
|
||||
element-loading-text="Loading..."
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
style="position:relative;"
|
||||
class="cornerstone-element"
|
||||
@mouseup="sliderMouseup"
|
||||
@contextmenu.prevent="onContextmenu"
|
||||
>
|
||||
<div id="canvas" ref="canvas" v-loading="loading" :element-loading-text="NSTip"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)" style="position:relative;" class="cornerstone-element"
|
||||
@mouseup="sliderMouseup" @contextmenu.prevent="onContextmenu">
|
||||
<!-- 临床数据 -->
|
||||
<div v-if="stack.isExistsClinicalData" class="info-cd" @click.stop="handleViewCD($event)">
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:clinicalData')" placement="bottom">
|
||||
@@ -18,46 +10,39 @@
|
||||
|
||||
</div>
|
||||
<!-- 切换访视 -->
|
||||
<div
|
||||
v-if="stack.imageRendered && isReadingTaskViewInOrder === 1"
|
||||
class="info-visit"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<div
|
||||
class="arrw_div_wrapper"
|
||||
:style="{cursor:stack.visitTaskNum <= minVistNum?'not-allowed':'pointer',color:stack.visitTaskNum <= minVistNum?'#888':'#fff'}"
|
||||
@click.stop.prevent="toggleSeries($event,-1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<div v-if="stack.imageRendered && isReadingTaskViewInOrder === 1" class="info-visit"
|
||||
@dblclick.stop="preventDefault($event)">
|
||||
<div class="arrw_div_wrapper"
|
||||
:style="{ cursor: stack.visitTaskNum <= minVistNum ? 'not-allowed' : 'pointer', color: stack.visitTaskNum <= minVistNum ? '#888' : '#fff' }"
|
||||
@click.stop.prevent="toggleSeries($event, -1)" @dblclick.stop="preventDefault($event)">
|
||||
<i class="el-icon-caret-left" />
|
||||
</div>
|
||||
<div class="blind_name_wrapper">
|
||||
{{ stack.taskBlindName }}
|
||||
</div>
|
||||
<div
|
||||
class="arrw_div_wrapper"
|
||||
:style="{cursor:stack.visitTaskNum >= maxVistNum?'not-allowed':'pointer',color:stack.visitTaskNum >= maxVistNum?'#888':'#fff'}"
|
||||
@click.stop.prevent="toggleSeries($event,1)"
|
||||
@dblclick.stop="preventDefault($event)"
|
||||
>
|
||||
<div class="arrw_div_wrapper"
|
||||
:style="{ cursor: stack.visitTaskNum >= maxVistNum ? 'not-allowed' : 'pointer', color: stack.visitTaskNum >= maxVistNum ? '#888' : '#fff' }"
|
||||
@click.stop.prevent="toggleSeries($event, 1)" @dblclick.stop="preventDefault($event)">
|
||||
<i class="el-icon-caret-right" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="info-series">
|
||||
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{ stack.taskBlindName }}</h2>
|
||||
<h2 v-if="isReadingShowSubjectInfo" style="color:#f44336;padding: 5px 0px;margin: 0;">{{ subjectCode }} {{
|
||||
stack.taskBlindName }}</h2>
|
||||
<div v-show="dicomInfo.series">Series: #{{ dicomInfo.series }}</div>
|
||||
<div>Image: #{{ dicomInfo.frame }}</div>
|
||||
<div>{{ dicomInfo.modality }}</div>
|
||||
</div>
|
||||
<div class="info-image">
|
||||
<div v-show="mousePosition.mo">
|
||||
Pos: {{ mousePosition.x?mousePosition.x.toFixed(0):'' }}, {{ mousePosition.y?mousePosition.y.toFixed(0):'' }}
|
||||
Pos: {{ mousePosition.x ? mousePosition.x.toFixed(0) : '' }}, {{ mousePosition.y ? mousePosition.y.toFixed(0) : '' }}
|
||||
</div>
|
||||
<div v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
||||
<div
|
||||
v-if="(dicomInfo.modality === 'CT' || dicomInfo.modality === 'DR' || dicomInfo.modality === 'CR') && mousePosition.mo">
|
||||
HU: {{ mousePosition.mo }}
|
||||
</div>
|
||||
<div v-else-if="(dicomInfo.modality === 'PT' && mousePosition.suv)">
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ?mousePosition.suv.toFixed(3) :mousePosition.suv.toFixed(digitPlaces) }}
|
||||
SUVbw(g/ml): {{ digitPlaces === -1 ? mousePosition.suv.toFixed(3) : mousePosition.suv.toFixed(digitPlaces) }}
|
||||
</div>
|
||||
<div v-else-if="mousePosition.mo">
|
||||
Density: {{ mousePosition.mo }}
|
||||
@@ -81,8 +66,12 @@
|
||||
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
|
||||
<!-- <div>{{ dicomInfo.time }}</div> -->
|
||||
</div>
|
||||
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 140px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer" @click.stop="goViewer($event)">
|
||||
<div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @click.stop.prevent="() => {return}" @mousedown.stop="sliderMousedown($event)" />
|
||||
<div ref="sliderBox" class="my_slider_box"
|
||||
style="position: absolute;right: 1px;height: calc(100% - 140px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer"
|
||||
@click.stop="goViewer($event)">
|
||||
<div :style="{ top: height + '%' }"
|
||||
style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move"
|
||||
@click.stop.prevent="() => { return }" @mousedown.stop="sliderMousedown($event)" />
|
||||
</div>
|
||||
<div style="position: absolute;left: 50%;top: 30px;color: #f44336;transform: translateX(-50%);">
|
||||
{{ markers.top }}
|
||||
@@ -117,7 +106,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<style>
|
||||
.my_slider_box:after{
|
||||
.my_slider_box:after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
bottom: -20px;
|
||||
@@ -306,7 +295,10 @@ export default {
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList', 'currentReadingTaskState'])
|
||||
...mapGetters(['visitTaskList', 'currentReadingTaskState']),
|
||||
NSTip() {
|
||||
return `NS: ${this.$store.state.trials.downloadTip}`
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
currentReadingTaskState: {
|
||||
@@ -562,7 +554,7 @@ export default {
|
||||
mouseDown(e) {
|
||||
this.image = e.detail.image
|
||||
var pointNearTool = this.pointNearTool(e)
|
||||
if (pointNearTool) {
|
||||
if (pointNearTool) {
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
@@ -574,7 +566,7 @@ export default {
|
||||
type: 'warning'
|
||||
}).then(() => {
|
||||
|
||||
}).catch(() => {})
|
||||
}).catch(() => { })
|
||||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
@@ -672,7 +664,7 @@ export default {
|
||||
this.sliderInfo.isMove = false
|
||||
},
|
||||
getMeasureData() {
|
||||
console.log('getMeasureData')
|
||||
console.log('getMeasureData')
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.stack.visitTaskId)
|
||||
this.measureData = this.visitTaskList[idx].MeasureData
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
@@ -889,7 +881,7 @@ export default {
|
||||
} else {
|
||||
// cornerstoneTools.setToolEnabledForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
|
||||
cornerstoneTools.setToolPassiveForElement(element, data.MeasureData.type, { mouseButtonMask: 1 })
|
||||
|
||||
|
||||
}
|
||||
if (this.stack.instanceId.includes(data.InstanceId) && ((this.stack.isExistMutiFrames && (data.MeasureData.frame === this.stack.frame) && data.MeasureData) || (!this.stack.isExistMutiFrames && data.MeasureData))) {
|
||||
// console.log('renderMeasuredData', this.stack.frame,data.MeasureData.frame,this.stack.isExistMutiFrames)
|
||||
@@ -991,32 +983,32 @@ export default {
|
||||
var idx = this.measureData.findIndex(item => item.MeasureData && item.MeasureData.data && item.MeasureData.data.uuid === toolState.data[i].uuid)
|
||||
if (idx > -1) {
|
||||
DicomEvent.$emit('setCollapseActive', this.measureData[idx])
|
||||
const measureData = {}
|
||||
// var markName = this.measureData[idx].OrderMarkName
|
||||
var markName = this.measureData[idx].MeasureData.data.remark
|
||||
if (this.activeToolName === 'Eraser' && this.disabledMarks.indexOf(markName) === -1) {
|
||||
const questionInfo = this.measureData[idx]
|
||||
measureData.orderMarkName = markName
|
||||
this.$emit('moveMeasureData', { measureData, questionInfo, orderMarkName: markName})
|
||||
}
|
||||
if ((this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) && this.activeToolName !== 'Eraser') {
|
||||
const questionInfo = this.measureData[idx]
|
||||
const canvas = this.canvas.querySelector('canvas')
|
||||
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
measureData.frame = this.stack.frame ? this.stack.frame : 0
|
||||
measureData.data = toolState.data[i]
|
||||
measureData.type = toolType
|
||||
measureData.thick = this.dicomInfo.thick
|
||||
measureData.location = this.dicomInfo.location
|
||||
measureData.ww = Math.round(viewport.voi.windowWidth)
|
||||
measureData.wc = Math.round(viewport.voi.windowCenter)
|
||||
measureData.data.active = false
|
||||
this.$emit('modifyMeasureData', { measureData, questionInfo })
|
||||
}
|
||||
|
||||
const measureData = {}
|
||||
// var markName = this.measureData[idx].OrderMarkName
|
||||
var markName = this.measureData[idx].MeasureData.data.remark
|
||||
if (this.activeToolName === 'Eraser' && this.disabledMarks.indexOf(markName) === -1) {
|
||||
const questionInfo = this.measureData[idx]
|
||||
measureData.orderMarkName = markName
|
||||
this.$emit('moveMeasureData', { measureData, questionInfo, orderMarkName: markName })
|
||||
}
|
||||
if ((this.disabledMarks.indexOf(markName) === -1 || !this.disabledMarks) && this.activeToolName !== 'Eraser') {
|
||||
const questionInfo = this.measureData[idx]
|
||||
const canvas = this.canvas.querySelector('canvas')
|
||||
measureData.pictureBaseStr = canvas.toDataURL('image/png', 1)
|
||||
measureData.studyId = this.stack.studyId
|
||||
measureData.seriesId = this.stack.seriesId
|
||||
measureData.instanceId = instanceId
|
||||
measureData.frame = this.stack.frame ? this.stack.frame : 0
|
||||
measureData.data = toolState.data[i]
|
||||
measureData.type = toolType
|
||||
measureData.thick = this.dicomInfo.thick
|
||||
measureData.location = this.dicomInfo.location
|
||||
measureData.ww = Math.round(viewport.voi.windowWidth)
|
||||
measureData.wc = Math.round(viewport.voi.windowCenter)
|
||||
measureData.data.active = false
|
||||
this.$emit('modifyMeasureData', { measureData, questionInfo })
|
||||
}
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -1118,7 +1110,7 @@ export default {
|
||||
const toolButtons = document.querySelectorAll('[data-tool]')
|
||||
// const scope = this
|
||||
Array.from(toolButtons).forEach((toolBtn) => {
|
||||
// Add the tool
|
||||
// Add the tool
|
||||
const toolName = toolBtn.getAttribute('data-tool')
|
||||
const apiTool = cornerstoneTools[`${toolName}Tool`]
|
||||
if (apiTool) {
|
||||
@@ -1126,17 +1118,17 @@ export default {
|
||||
|
||||
if (!toolAlreadyAddedToElement) {
|
||||
if (toolName === 'Length') {
|
||||
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true }})
|
||||
cornerstoneTools.addToolForElement(element, LengthTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true } })
|
||||
} else if (toolName === 'Bidirectional') {
|
||||
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
|
||||
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
|
||||
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true }})
|
||||
// cornerstoneTools.addToolForElement(element, BidirectionalTool, { digits: this.digitPlaces })
|
||||
// , handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true
|
||||
cornerstoneTools.addToolForElement(element, BidirectionalTool, { configuration: { digits: this.digitPlaces, hideHandlesIfMoving: true } })
|
||||
} else if (toolName === 'ArrowAnnotate') {
|
||||
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
|
||||
cornerstoneTools.addToolForElement(element, ArrowAnnotateTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true } })
|
||||
} else if (toolName === 'RectangleRoi') {
|
||||
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true }})
|
||||
cornerstoneTools.addToolForElement(element, RectangleRoiTool, { configuration: { allowEmptyLabel: true, handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true } })
|
||||
} else if (toolName === 'CircleRoi') {
|
||||
cornerstoneTools.addToolForElement(element, CircleRoiTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true, showMinMax: true }})
|
||||
cornerstoneTools.addToolForElement(element, CircleRoiTool, { configuration: { handleRadius: false, drawHandlesOnHover: true, hideHandlesIfMoving: true, digits: this.digitPlaces, drawHandles: true, showMinMax: true } })
|
||||
} else {
|
||||
cornerstoneTools.addToolForElement(element, apiTool)
|
||||
}
|
||||
@@ -1162,10 +1154,10 @@ export default {
|
||||
mouseButtonMask: 4
|
||||
})
|
||||
|
||||
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
|
||||
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
|
||||
// }
|
||||
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
|
||||
// if (!cornerstoneTools.getToolForElement(element, OrientationMarkersTool)) {
|
||||
// cornerstoneTools.addToolForElement(element, OrientationMarkersTool)
|
||||
// }
|
||||
// cornerstoneTools.setToolActiveForElement(element, 'OrientationMarkers', { })
|
||||
}
|
||||
|
||||
// cornerstoneTools.addStackStateManager(this.canvas, ['stack', 'stackPrefetch', 'playClip'])
|
||||
@@ -1210,9 +1202,8 @@ export default {
|
||||
data.string('x00080030')
|
||||
)
|
||||
this.dicomInfo.series = data.string('x00200011')
|
||||
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${
|
||||
this.stack.imageIds.length
|
||||
}`
|
||||
this.dicomInfo.frame = `${this.stack.currentImageIdIndex + 1}/${this.stack.imageIds.length
|
||||
}`
|
||||
this.dicomInfo.size = `${data.uint16('x00280011')}*${data.uint16(
|
||||
'x00280010'
|
||||
)}`
|
||||
@@ -1392,9 +1383,9 @@ export default {
|
||||
var element = cornerstone.getEnabledElement(this.canvas)
|
||||
const { rowPixelSpacing, colPixelSpacing } = this.getPixelSpacing(element.image)
|
||||
const dx =
|
||||
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
|
||||
(data.handles.end.x - data.handles.start.x) * (colPixelSpacing || 1)
|
||||
const dy =
|
||||
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
|
||||
(data.handles.end.y - data.handles.start.y) * (rowPixelSpacing || 1)
|
||||
const length = Math.sqrt(dx * dx + dy * dy)
|
||||
|
||||
return length.toFixed(this.digitPlaces)
|
||||
@@ -1408,9 +1399,9 @@ export default {
|
||||
if (imagePlane) {
|
||||
return {
|
||||
rowPixelSpacing:
|
||||
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
|
||||
imagePlane.rowPixelSpacing || imagePlane.rowImagePixelSpacing,
|
||||
colPixelSpacing:
|
||||
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
|
||||
imagePlane.columnPixelSpacing || imagePlane.colImagePixelSpacing
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1462,7 +1453,7 @@ export default {
|
||||
},
|
||||
debounce(callback, delay) {
|
||||
let timerId
|
||||
return function() {
|
||||
return function () {
|
||||
clearTimeout(timerId)
|
||||
timerId = setTimeout(() => {
|
||||
callback.apply(this, arguments)
|
||||
@@ -1480,7 +1471,7 @@ export default {
|
||||
if (imageId) {
|
||||
ToolStateManager.clearImageIdToolState(imageId)
|
||||
let elements = cornerstone.getEnabledElementsByImageId(imageId)
|
||||
elements.map(el=>{
|
||||
elements.map(el => {
|
||||
cornerstone.updateImage(el.element)
|
||||
})
|
||||
}
|
||||
@@ -1766,7 +1757,7 @@ export default {
|
||||
this.activeToolName = toolName
|
||||
this.$nextTick(() => {
|
||||
// console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional'))
|
||||
|
||||
|
||||
if (toolName === 'Zoom') {
|
||||
cornerstoneTools.setToolActiveForElement(this.canvas, 'Zoom', {
|
||||
mouseButtonMask: [1, 2]
|
||||
@@ -1920,7 +1911,7 @@ export default {
|
||||
for (const [key, value] of searchParams.entries()) {
|
||||
params[key] = value
|
||||
}
|
||||
if (isNaN(params.frame)){
|
||||
if (isNaN(params.frame)) {
|
||||
params.frame = 0
|
||||
}
|
||||
return params
|
||||
@@ -1942,88 +1933,102 @@ export default {
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.context-menu-wrapper{
|
||||
position: absolute;
|
||||
ul{
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
.context-menu-wrapper {
|
||||
position: absolute;
|
||||
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0px;
|
||||
padding: 0px;
|
||||
background: #343333;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 3px;
|
||||
height: auto;
|
||||
min-height: 50px;
|
||||
line-height: 1.5em;
|
||||
width: 80px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.menu {
|
||||
li {
|
||||
padding: 2px 5px;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #666;
|
||||
|
||||
div {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.submenu {
|
||||
position: absolute;
|
||||
left: 77px;
|
||||
top: -1px;
|
||||
background: #343333;
|
||||
color: #fff;
|
||||
margin: 0;
|
||||
border: 1px solid #2a2a2a;
|
||||
border-radius: 3px;
|
||||
height: auto;
|
||||
min-height: 50px;
|
||||
line-height: 1.5em;
|
||||
width:80px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.menu{
|
||||
display: none;
|
||||
|
||||
li {
|
||||
padding: 2px 5px;
|
||||
position: relative;
|
||||
border-bottom: 1px solid #666;
|
||||
div{
|
||||
|
||||
div {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
.submenu{
|
||||
position: absolute;
|
||||
left: 77px;
|
||||
top: -1px;
|
||||
background: #343333;
|
||||
color: #fff;
|
||||
display: none;
|
||||
li {
|
||||
padding: 2px 5px;
|
||||
border-bottom: 1px solid #666;
|
||||
div{
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.menu li:hover{
|
||||
background-color: #ff5722;
|
||||
.submenu{
|
||||
display:block;
|
||||
}
|
||||
}
|
||||
.menu_active{
|
||||
cursor: pointer;
|
||||
}
|
||||
.menu_disabled{
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
}
|
||||
.info-visit{
|
||||
position: absolute;
|
||||
left:50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.arrw_div_wrapper{
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
.blind_name_wrapper{
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding:0 10px;
|
||||
font-size: 14px;
|
||||
|
||||
.menu li:hover {
|
||||
background-color: #ff5722;
|
||||
|
||||
.submenu {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
.info-cd{
|
||||
|
||||
.menu_active {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.menu_disabled {
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.info-visit {
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
top: 5px;
|
||||
transform: translateX(-50%);
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.arrw_div_wrapper {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background-color: #3f3f3f;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
border-radius: 10%;
|
||||
}
|
||||
|
||||
.blind_name_wrapper {
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
background-color: #00000057;
|
||||
color: #fff;
|
||||
padding: 0 10px;
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
|
||||
.info-cd {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
top: 5px;
|
||||
@@ -2032,6 +2037,7 @@ export default {
|
||||
font-size: 18px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.info-series {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
@@ -2041,6 +2047,7 @@ export default {
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.info-image {
|
||||
position: absolute;
|
||||
left: 10px;
|
||||
@@ -2060,6 +2067,7 @@ export default {
|
||||
font-size: 12px;
|
||||
/* z-index: 1; */
|
||||
}
|
||||
|
||||
.info-instance {
|
||||
position: absolute;
|
||||
right: 15px;
|
||||
@@ -2092,6 +2100,7 @@ export default {
|
||||
margin: 10px;
|
||||
cursor: default;
|
||||
}
|
||||
|
||||
.menu__item:hover {
|
||||
color: #ff0000;
|
||||
}
|
||||
@@ -2111,11 +2120,12 @@ li:hover {
|
||||
background-color: #e0e0e2;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.msg-div {
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
color: #000;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
background-color: rgba(255, 255, 255, 0.5);
|
||||
color: #000;
|
||||
padding: 5px 20px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user