Merge branch 'main' into uat_us
commit
a3e79db023
File diff suppressed because it is too large
Load Diff
|
|
@ -15,11 +15,12 @@
|
||||||
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
|
"i18n:en": "node i18nGenerate.js lang=en keyCol=5 valCol=7"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@aws-sdk/client-s3": "^3.726.1",
|
"@aws-sdk/client-s3": "3.726.1",
|
||||||
"@cornerstonejs/adapters": "4.19.2",
|
"@cornerstonejs/adapters": "^4.19.2",
|
||||||
"@cornerstonejs/calculate-suv": "^1.1.0",
|
"@cornerstonejs/calculate-suv": "^1.1.0",
|
||||||
"@cornerstonejs/core": "^4.19.2",
|
"@cornerstonejs/core": "^4.19.2",
|
||||||
"@cornerstonejs/dicom-image-loader": "^4.19.2",
|
"@cornerstonejs/dicom-image-loader": "^4.19.2",
|
||||||
|
"@cornerstonejs/polymorphic-segmentation": "^4.19.2",
|
||||||
"@cornerstonejs/tools": "^4.19.2",
|
"@cornerstonejs/tools": "^4.19.2",
|
||||||
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
"@fingerprintjs/fingerprintjs": "^4.6.2",
|
||||||
"@icr/polyseg-wasm": "^0.4.0",
|
"@icr/polyseg-wasm": "^0.4.0",
|
||||||
|
|
@ -38,7 +39,7 @@
|
||||||
"dcmjs": "^0.29.8",
|
"dcmjs": "^0.29.8",
|
||||||
"dicom-parser": "^1.8.9",
|
"dicom-parser": "^1.8.9",
|
||||||
"dicomedit": "^0.1.0",
|
"dicomedit": "^0.1.0",
|
||||||
"echarts": "^4.8.0",
|
"echarts": "^6.0.0",
|
||||||
"element-ui": "^2.15.14",
|
"element-ui": "^2.15.14",
|
||||||
"exceljs": "^4.4.0",
|
"exceljs": "^4.4.0",
|
||||||
"file-saver": "^2.0.5",
|
"file-saver": "^2.0.5",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function addOrUpdateFileUploadRecord(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/addOrUpdateFileUploadRecord`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function batchAddSyncFileTask(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/batchAddSyncFileTask`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSubjectUploadRecordList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/getSubjectUploadRecordList`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getFileUploadRecordList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/getFileUploadRecordList`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getUploadFileSyncRecordList(params) {
|
||||||
|
return request({
|
||||||
|
url: `/FileUploadRecord/getUploadFileSyncRecordList`,
|
||||||
|
method: 'post',
|
||||||
|
data: params
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
@ -8,20 +8,49 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getReportsChartData } from "@/api/reading"
|
import { getReportsChartData } from "@/api/reading"
|
||||||
let echarts = require('echarts/lib/echarts');
|
import * as echarts from 'echarts/core';
|
||||||
|
import { LineChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
// 内置数据转换器组件 (filter, sort)
|
||||||
|
TransformComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
// 标签自动布局、全局过渡动画等特性
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
LineChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
// let echarts = require('echarts/lib/echarts');
|
||||||
|
|
||||||
// 按需引入图表
|
// 按需引入图表
|
||||||
// require('echarts/lib/chart/bar');
|
// require('echarts/lib/chart/bar');
|
||||||
require('echarts/lib/chart/line');
|
// require('echarts/lib/chart/line');
|
||||||
// require('echarts/lib/chart/pie');
|
// require('echarts/lib/chart/pie');
|
||||||
// require('echarts/lib/chart/scatter');
|
// require('echarts/lib/chart/scatter');
|
||||||
|
|
||||||
// 按需引入组件
|
// 按需引入组件
|
||||||
require('echarts/lib/component/tooltip');
|
// require('echarts/lib/component/tooltip');
|
||||||
require('echarts/lib/component/title');
|
// require('echarts/lib/component/title');
|
||||||
require('echarts/lib/component/legend');
|
// require('echarts/lib/component/legend');
|
||||||
require('echarts/lib/component/grid');
|
// require('echarts/lib/component/grid');
|
||||||
require('echarts/lib/component/dataZoom');
|
// require('echarts/lib/component/dataZoom');
|
||||||
export default {
|
export default {
|
||||||
name: "readingChart",
|
name: "readingChart",
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -151,7 +180,13 @@ export default {
|
||||||
text: obj.title,
|
text: obj.title,
|
||||||
textStyle: {
|
textStyle: {
|
||||||
color: "#fff"
|
color: "#fff"
|
||||||
}
|
},
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 50,
|
||||||
|
bottom: 30
|
||||||
},
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
|
|
@ -193,6 +228,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
axisLine: {
|
axisLine: {
|
||||||
|
show: true,
|
||||||
lineStyle: {
|
lineStyle: {
|
||||||
color: '#fff',
|
color: '#fff',
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1174,6 +1174,7 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
let arr = []
|
let arr = []
|
||||||
|
let uploadBatchId = scope.$guid()
|
||||||
for (let i = 0; i < seriesList.length; i++) {
|
for (let i = 0; i < seriesList.length; i++) {
|
||||||
let v = seriesList[i]
|
let v = seriesList[i]
|
||||||
let instanceList = []
|
let instanceList = []
|
||||||
|
|
@ -1266,6 +1267,16 @@ export default {
|
||||||
) {
|
) {
|
||||||
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileName: o.file.name,
|
||||||
|
fileSize: o.file.size,
|
||||||
|
fileType: 'application/dicom',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 5,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (!res || !res.url) {
|
if (!res || !res.url) {
|
||||||
|
|
@ -1289,7 +1300,17 @@ export default {
|
||||||
let OSSclient = scope.OSSclient
|
let OSSclient = scope.OSSclient
|
||||||
let seriesRes = await OSSclient.put(
|
let seriesRes = await OSSclient.put(
|
||||||
thumbnailPath,
|
thumbnailPath,
|
||||||
blob
|
blob,
|
||||||
|
{
|
||||||
|
fileName: `${v.seriesUid}.jpg`,
|
||||||
|
fileSize: blob.size,
|
||||||
|
fileType: 'image/jpeg',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 6,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId
|
||||||
|
}
|
||||||
)
|
)
|
||||||
if (seriesRes && seriesRes.url) {
|
if (seriesRes && seriesRes.url) {
|
||||||
ImageResizePath = scope.$getObjectName(
|
ImageResizePath = scope.$getObjectName(
|
||||||
|
|
@ -1430,7 +1451,20 @@ export default {
|
||||||
}
|
}
|
||||||
let OSSclient = scope.OSSclient
|
let OSSclient = scope.OSSclient
|
||||||
try {
|
try {
|
||||||
let seriesRes = await OSSclient.put(thumbnailPath, blob)
|
let seriesRes = await OSSclient.put(
|
||||||
|
thumbnailPath,
|
||||||
|
blob,
|
||||||
|
{
|
||||||
|
fileName: `${v.seriesUid}.jpg`,
|
||||||
|
fileSize: blob.size,
|
||||||
|
fileType: 'image/jpeg',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 6,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId
|
||||||
|
}
|
||||||
|
)
|
||||||
if (seriesRes && seriesRes.url) {
|
if (seriesRes && seriesRes.url) {
|
||||||
o.ImageResizePath = scope.$getObjectName(seriesRes.url)
|
o.ImageResizePath = scope.$getObjectName(seriesRes.url)
|
||||||
}
|
}
|
||||||
|
|
@ -1448,6 +1482,7 @@ export default {
|
||||||
if (scope.IsImageSegment) {
|
if (scope.IsImageSegment) {
|
||||||
params.IsImageSegmentLabel = true
|
params.IsImageSegmentLabel = true
|
||||||
}
|
}
|
||||||
|
params.UploadBatchId = uploadBatchId
|
||||||
addOrUpdateArchiveTaskStudy(params)
|
addOrUpdateArchiveTaskStudy(params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
||||||
|
|
|
||||||
|
|
@ -548,8 +548,9 @@ export default {
|
||||||
})
|
})
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
this.studyMonitorId = res.Result
|
this.studyMonitorId = res.Result
|
||||||
|
let uploadBatchId = this.$guid()
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
funArr.push(this.handleUploadTask(this.selectArr, i))
|
funArr.push(this.handleUploadTask(this.selectArr, i, uploadBatchId))
|
||||||
}
|
}
|
||||||
if (funArr.length > 0) {
|
if (funArr.length > 0) {
|
||||||
let res = await Promise.all(funArr)
|
let res = await Promise.all(funArr)
|
||||||
|
|
@ -560,7 +561,7 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 并发上传
|
// 并发上传
|
||||||
async handleUploadTask(arr, index) {
|
async handleUploadTask(arr, index, uploadBatchId) {
|
||||||
if (!this.uploadVisible) return
|
if (!this.uploadVisible) return
|
||||||
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
||||||
file.status = 1
|
file.status = 1
|
||||||
|
|
@ -576,7 +577,7 @@ export default {
|
||||||
}
|
}
|
||||||
file.curPath = path
|
file.curPath = path
|
||||||
const fileData = await this.fileToBlob(file.file)
|
const fileData = await this.fileToBlob(file.file)
|
||||||
let res = await this.fileToOss(path, fileData, file)
|
let res = await this.fileToOss(path, fileData, file, uploadBatchId)
|
||||||
if (res) {
|
if (res) {
|
||||||
file.status = 2
|
file.status = 2
|
||||||
this.successFileList.push({
|
this.successFileList.push({
|
||||||
|
|
@ -610,13 +611,13 @@ export default {
|
||||||
}
|
}
|
||||||
let ind = arr.findIndex((item) => item.status === 0)
|
let ind = arr.findIndex((item) => item.status === 0)
|
||||||
if (ind >= 0) {
|
if (ind >= 0) {
|
||||||
return this.handleUploadTask(arr, ind)
|
return this.handleUploadTask(arr, ind, uploadBatchId)
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// file上传到oss
|
// file上传到oss
|
||||||
async fileToOss(path, file, item) {
|
async fileToOss(path, file, item, uploadBatchId) {
|
||||||
try {
|
try {
|
||||||
let res = await this.OSSclient.multipartUpload(
|
let res = await this.OSSclient.multipartUpload(
|
||||||
{
|
{
|
||||||
|
|
@ -629,6 +630,17 @@ export default {
|
||||||
if (item.uploadFileSize > file.fileSize) {
|
if (item.uploadFileSize > file.fileSize) {
|
||||||
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileName: item.name,
|
||||||
|
fileSize: item.size,
|
||||||
|
fileType: item.fileType,
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 7,
|
||||||
|
trialId: this.$route.query.trialId,
|
||||||
|
subjectId: this.currentRow.SubjectId,
|
||||||
|
subjectVisitId: this.currentRow.SourceSubjectVisitId,
|
||||||
|
studyCode: this.SubjectCode
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
import resize from './resize'
|
||||||
|
|
||||||
|
const install = function (Vue) {
|
||||||
|
// 绑定v-adaptive指令
|
||||||
|
Vue.directive('resize', resize)
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (window.Vue) {
|
||||||
|
// window['adaptive'] = adaptive
|
||||||
|
// // eslint-disable-next-line no-undef
|
||||||
|
// Vue.use(install)
|
||||||
|
// }
|
||||||
|
|
||||||
|
resize.install = install
|
||||||
|
|
||||||
|
export default resize
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
const map = new WeakMap()
|
||||||
|
const ob = new ResizeObserver(entries => {
|
||||||
|
for (const entry of entries) {
|
||||||
|
const handler = map.get(entry.target)
|
||||||
|
if (handler) {
|
||||||
|
const { inlineSize, blockSize } = entry.contentBoxSize[0]
|
||||||
|
handler({ width: inlineSize, height: blockSize })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
export default {
|
||||||
|
bind(el, binding) {
|
||||||
|
map.set(el, binding.value)
|
||||||
|
ob.observe(el)
|
||||||
|
},
|
||||||
|
unbind(el) {
|
||||||
|
ob.unobserve(el)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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="1775115523115" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5347" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M458.105263 970.105263h-215.578947V264.084211h215.578947V970.105263z m-161.68421-53.894737h107.789473V317.978947h-107.789473V916.210526z" fill="#ffffff" p-id="5348"></path><path d="M296.421053 970.105263h-215.578948V479.663158h215.578948V970.105263z m-161.684211-53.894737h107.789474V533.557895h-107.789474V916.210526zM943.157895 970.105263h-215.578948V479.663158h215.578948V970.105263z m-161.684211-53.894737h107.789474V533.557895h-107.789474V916.210526zM619.789474 970.105263h-215.578948V53.894737h215.578948v916.210526z m-161.684211-53.894737h107.789474V107.789474h-107.789474v808.421052z" fill="#ffffff" p-id="5349"></path><path d="M781.473684 970.105263h-215.578947V264.084211h215.578947V970.105263z m-161.68421-53.894737h107.789473V317.978947h-107.789473V916.210526z" fill="#ffffff" p-id="5350"></path></svg>
|
||||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -70,6 +70,9 @@ import FB from '@/components/feedBack/index'
|
||||||
Vue.use(FB)
|
Vue.use(FB)
|
||||||
import FBT from '@/components/feedBackTable/index'
|
import FBT from '@/components/feedBackTable/index'
|
||||||
Vue.use(FBT)
|
Vue.use(FBT)
|
||||||
|
import resize from '@/directive/resize/index'
|
||||||
|
// 表格自适应指令
|
||||||
|
Vue.use(resize)
|
||||||
import adaptive from '@/directive/adaptive/index'
|
import adaptive from '@/directive/adaptive/index'
|
||||||
// 表格自适应指令
|
// 表格自适应指令
|
||||||
Vue.use(adaptive)
|
Vue.use(adaptive)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { anonymization } from './anonymization'
|
import { anonymization } from './anonymization'
|
||||||
export const dcmUpload = async function (data, config, progressFn) {
|
export const dcmUpload = async function (data, config, progressFn, fileInfo) {
|
||||||
return new Promise(async resolve => {
|
return new Promise(async resolve => {
|
||||||
try {
|
try {
|
||||||
// let blob = await encoder(file, config)
|
// let blob = await encoder(file, config)
|
||||||
|
|
@ -8,7 +8,8 @@ export const dcmUpload = async function (data, config, progressFn) {
|
||||||
if (config) {
|
if (config) {
|
||||||
blob = await anonymization(data.file, config)
|
blob = await anonymization(data.file, config)
|
||||||
}
|
}
|
||||||
let res = await Vue.prototype.OSSclient.multipartUpload(Object.assign(data, { file: blob.blob }), progressFn)
|
|
||||||
|
let res = await Vue.prototype.OSSclient.multipartUpload(Object.assign(data, { file: blob.blob }), progressFn, fileInfo)
|
||||||
resolve({
|
resolve({
|
||||||
...res,
|
...res,
|
||||||
image: blob.pixelDataElement
|
image: blob.pixelDataElement
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ const stream = require('stream')
|
||||||
import Vue from 'vue'
|
import Vue from 'vue'
|
||||||
import { customerHttp, OSSclose } from "@/utils/multipartUpload/oss"
|
import { customerHttp, OSSclose } from "@/utils/multipartUpload/oss"
|
||||||
import { exist, AWSclose } from "@/utils/multipartUpload/aws"
|
import { exist, AWSclose } from "@/utils/multipartUpload/aws"
|
||||||
|
import { addOrUpdateFileUploadRecord } from '@/api/file'
|
||||||
const { GetObjectStoreToken } = require('../api/user.js')
|
const { GetObjectStoreToken } = require('../api/user.js')
|
||||||
const {
|
const {
|
||||||
S3Client,
|
S3Client,
|
||||||
|
|
@ -22,7 +23,6 @@ async function ossGenerateSTS() {
|
||||||
res = await GetObjectStoreToken()
|
res = await GetObjectStoreToken()
|
||||||
localStorage.setItem('stsToken', JSON.stringify(res))
|
localStorage.setItem('stsToken', JSON.stringify(res))
|
||||||
}
|
}
|
||||||
|
|
||||||
// res.Result.ObjectStoreUse = 'AWS';
|
// res.Result.ObjectStoreUse = 'AWS';
|
||||||
Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] }
|
Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] }
|
||||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse;
|
Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse;
|
||||||
|
|
@ -34,7 +34,8 @@ async function ossGenerateSTS() {
|
||||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||||
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
|
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
|
||||||
Vue.prototype.OSSclient = {
|
Vue.prototype.OSSclient = {
|
||||||
put: async function (objectName, object) {
|
put: async function (objectName, object, fileInfo = {}) {
|
||||||
|
|
||||||
OSSclient = await RefreshClient(OSSclient)
|
OSSclient = await RefreshClient(OSSclient)
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -52,6 +53,15 @@ async function ossGenerateSTS() {
|
||||||
}
|
}
|
||||||
let res = await OSSclient.put(objectName, object)
|
let res = await OSSclient.put(objectName, object)
|
||||||
if (res && res.url) {
|
if (res && res.url) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const trialId = urlParams.get('trialId')
|
||||||
|
if (Object.keys(fileInfo).length !== 0) {
|
||||||
|
let params = Object.assign({path: objectName}, fileInfo)
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
} else if (trialId) {
|
||||||
|
let params = { trialId }
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: objectName,
|
name: objectName,
|
||||||
url: res.url
|
url: res.url
|
||||||
|
|
@ -65,7 +75,7 @@ async function ossGenerateSTS() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
multipartUpload: async (data, progress) => {
|
multipartUpload: async (data, progress, fileInfo = {}) => {
|
||||||
OSSclient = await RefreshClient(OSSclient)
|
OSSclient = await RefreshClient(OSSclient)
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
|
|
@ -95,6 +105,16 @@ async function ossGenerateSTS() {
|
||||||
}
|
}
|
||||||
let res = await customerHttp(OSSclient, data, progress);
|
let res = await customerHttp(OSSclient, data, progress);
|
||||||
if (res) {
|
if (res) {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
const trialId = urlParams.get('trialId')
|
||||||
|
if (Object.keys(fileInfo).length !== 0) {
|
||||||
|
let params = Object.assign({path: data.path}, fileInfo)
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
} else if (trialId) {
|
||||||
|
let params = { trialId }
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
}
|
||||||
|
|
||||||
resolve({
|
resolve({
|
||||||
name: data.path,
|
name: data.path,
|
||||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(res.name)
|
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(res.name)
|
||||||
|
|
@ -169,17 +189,17 @@ async function ossGenerateSTS() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
Vue.prototype.OSSclient = {
|
Vue.prototype.OSSclient = {
|
||||||
put: async function (objectName, object) {
|
put: async function (objectName, object, fileInfo = {}) {
|
||||||
let data = {
|
let data = {
|
||||||
file: object,
|
file: object,
|
||||||
path: objectName
|
path: objectName
|
||||||
}
|
}
|
||||||
aws = await RefreshClient(aws);
|
aws = await RefreshClient(aws);
|
||||||
return uploadAWS(aws, data, () => { });
|
return uploadAWS(aws, data, () => { }, fileInfo);
|
||||||
},
|
},
|
||||||
multipartUpload: async (data, progress) => {
|
multipartUpload: async (data, progress, fileInfo = {}) => {
|
||||||
aws = await RefreshClient(aws);
|
aws = await RefreshClient(aws);
|
||||||
return uploadAWS(aws, data, progress);
|
return uploadAWS(aws, data, progress, fileInfo);
|
||||||
},
|
},
|
||||||
close: () => {
|
close: () => {
|
||||||
AWSclose();
|
AWSclose();
|
||||||
|
|
@ -189,7 +209,7 @@ async function ossGenerateSTS() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// AWS上传函数
|
// AWS上传函数
|
||||||
function uploadAWS(aws, data, progress) {
|
function uploadAWS(aws, data, progress, fileInfo) {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const { file, path } = data;
|
const { file, path } = data;
|
||||||
|
|
@ -211,6 +231,16 @@ function uploadAWS(aws, data, progress) {
|
||||||
data.path = data.path.replace(`/${bucketName}/`, '');
|
data.path = data.path.replace(`/${bucketName}/`, '');
|
||||||
await exist(aws, bucketName, data, progress, (path, status) => {
|
await exist(aws, bucketName, data, progress, (path, status) => {
|
||||||
if (status === 'success') {
|
if (status === 'success') {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search)
|
||||||
|
|
||||||
|
const trialId = urlParams.get('trialId')
|
||||||
|
if (Object.keys(fileInfo).length !== 0) {
|
||||||
|
let params = Object.assign({path: decodeUtf8(curPath)}, fileInfo)
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
} else if (trialId) {
|
||||||
|
let params = { trialId }
|
||||||
|
addOrUpdateFileUploadRecord(params)
|
||||||
|
}
|
||||||
resolve({
|
resolve({
|
||||||
name: decodeUtf8(curPath),
|
name: decodeUtf8(curPath),
|
||||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(curPath)
|
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(curPath)
|
||||||
|
|
|
||||||
|
|
@ -2,8 +2,8 @@
|
||||||
<div ref="mapbox" class="map-wrapper" />
|
<div ref="mapbox" class="map-wrapper" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import 'modules/echarts/map/js/world.js'
|
// import 'modules/echarts/map/js/world.js'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
export default {
|
export default {
|
||||||
props: {
|
props: {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div ref="trials_stats" style="width:100%;height:100%;" />
|
<div ref="trials_stats" style="width:100%;height:100%;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getTrialCountRank } from '@/api/dashboard'
|
import { getTrialCountRank } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 5
|
const Count = 5
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div ref="enroll_stats" style="width:100%;height:100%;" />
|
<div ref="enroll_stats" style="width:100%;height:100%;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getEnrollDataByQuarter } from '@/api/dashboard'
|
import { getEnrollDataByQuarter } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 6
|
const Count = 6
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div ref="reviewers_stats" style="width:100%;height:100%;padding:5px;" />
|
<div ref="reviewers_stats" style="width:100%;height:100%;padding:5px;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReviewersByRank } from '@/api/dashboard'
|
import { getReviewersByRank } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
export default {
|
export default {
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div ref="monthly_reading_stats" style="width:100%;height:100%;" />
|
<div ref="monthly_reading_stats" style="width:100%;height:100%;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReadingDataByMonth } from '@/api/dashboard'
|
import { getReadingDataByMonth } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 6
|
const Count = 6
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div ref="reading_rank" class="reading-rank" />
|
<div ref="reading_rank" class="reading-rank" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReadingDataRank } from '@/api/dashboard'
|
import { getReadingDataRank } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
const Count = 5
|
const Count = 5
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div ref="reading_stats" style="width:100%;height:100%;padding-top:5px;" />
|
<div ref="reading_stats" style="width:100%;height:100%;padding-top:5px;" />
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import { getReadingDataByType } from '@/api/dashboard'
|
import { getReadingDataByType } from '@/api/dashboard'
|
||||||
import { fontSize } from 'utils/fontsize'
|
import { fontSize } from 'utils/fontsize'
|
||||||
export default {
|
export default {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="adReview_wrapper">
|
<div class="adReview_wrapper">
|
||||||
<el-card
|
<el-card v-if="isReadingShowSubjectInfo" shadow="never" :body-style="{ padding: '10px' }"
|
||||||
v-if="isReadingShowSubjectInfo"
|
style="margin-bottom: 10px">
|
||||||
shadow="never"
|
|
||||||
:body-style="{ padding: '10px' }"
|
|
||||||
style="margin-bottom: 10px"
|
|
||||||
>
|
|
||||||
<h4>
|
<h4>
|
||||||
<!-- 受试者: -->
|
<!-- 受试者: -->
|
||||||
{{ $t("trials:adReview:title:subject") }}
|
{{ $t("trials:adReview:title:subject") }}
|
||||||
|
|
@ -17,14 +13,11 @@
|
||||||
<!-- <div slot="header" class="clearfix">
|
<!-- <div slot="header" class="clearfix">
|
||||||
<span style="font-weight: bold;">评估结果</span>
|
<span style="font-weight: bold;">评估结果</span>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div
|
<div slot="header" style="
|
||||||
slot="header"
|
|
||||||
style="
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
"
|
">
|
||||||
>
|
|
||||||
<!-- 评估结果 -->
|
<!-- 评估结果 -->
|
||||||
<div style="font-weight: bold">
|
<div style="font-weight: bold">
|
||||||
{{ $t("trials:adReview:title:result") }}
|
{{ $t("trials:adReview:title:result") }}
|
||||||
|
|
@ -39,46 +32,33 @@
|
||||||
|
|
||||||
<el-table :data="adInfo.VisitInfoList" style="width: 100%">
|
<el-table :data="adInfo.VisitInfoList" style="width: 100%">
|
||||||
<!-- 访视名称 -->
|
<!-- 访视名称 -->
|
||||||
<el-table-column
|
<el-table-column prop="VisitName" :label="$t('trials:adReview:table:visitName')" show-overflow-tooltip
|
||||||
prop="VisitName"
|
width="150" />
|
||||||
:label="$t('trials:adReview:table:visitName')"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="150"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- 评估结果 -->
|
<!-- 评估结果 -->
|
||||||
<el-table-column
|
<el-table-column v-for="j in judgeQuestion" :key="j.armEnum" :label="j.armEnum === 1
|
||||||
v-for="j in judgeQuestion"
|
|
||||||
:key="j.armEnum"
|
|
||||||
:label="
|
|
||||||
j.armEnum === 1
|
|
||||||
? $t('trials:adReview:table:viewR1')
|
? $t('trials:adReview:table:viewR1')
|
||||||
: j.armEnum === 2
|
: j.armEnum === 2
|
||||||
? $t('trials:adReview:table:viewR2')
|
? $t('trials:adReview:table:viewR2')
|
||||||
: $fd('ArmEnum', j.armEnum)
|
: $fd('ArmEnum', j.armEnum)
|
||||||
"
|
" align="center" prop="">
|
||||||
align="center"
|
|
||||||
prop=""
|
|
||||||
>
|
|
||||||
<template>
|
<template>
|
||||||
<el-table-column
|
<el-table-column v-for="(qs, i) in j.judgeQuestionList" :key="i" prop="" :label="qs" show-overflow-tooltip
|
||||||
v-for="(qs, i) in j.judgeQuestionList"
|
width="150">
|
||||||
:key="i"
|
|
||||||
prop=""
|
|
||||||
:label="qs"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="150"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 1">
|
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 1">
|
||||||
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode">
|
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode">
|
||||||
{{ $fd(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode,parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))
|
{{
|
||||||
|
$fd(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode,
|
||||||
|
parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))
|
||||||
}}
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>
|
<span v-else>
|
||||||
{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}
|
{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit && !isNaN(parseFloat(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))">{{ $fd('ValueUnit', parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit)) }}</span>
|
<span
|
||||||
|
v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit && !isNaN(parseFloat(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))">{{
|
||||||
|
$fd('ValueUnit', parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit)) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div v-else-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 2">
|
<div v-else-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 2">
|
||||||
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer">
|
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer">
|
||||||
|
|
@ -86,15 +66,11 @@
|
||||||
{{ $fd("YesOrNo", scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer) }}
|
{{ $fd("YesOrNo", scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer) }}
|
||||||
</span>
|
</span>
|
||||||
<!-- 查看详情 -->
|
<!-- 查看详情 -->
|
||||||
<el-button
|
<el-button type="text" style="margin-left: 5px" @click="
|
||||||
type="text"
|
|
||||||
style="margin-left: 5px"
|
|
||||||
@click="
|
|
||||||
handleViewDetail(
|
handleViewDetail(
|
||||||
scope.row.VisitTaskInfoList[j.index].GlobalVisitTaskId
|
scope.row.VisitTaskInfoList[j.index].GlobalVisitTaskId
|
||||||
)
|
)
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ $t("trials:adReview:table:view") }}
|
{{ $t("trials:adReview:table:view") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -119,60 +95,34 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<!-- 查看详情 -->
|
<!-- 查看详情 -->
|
||||||
<el-table-column
|
<el-table-column :label="criterionType === 10
|
||||||
:label="
|
|
||||||
criterionType === 10
|
|
||||||
? $t('trials:adReview:table:visitInfoview')
|
? $t('trials:adReview:table:visitInfoview')
|
||||||
: $t('trials:adReview:table:view')
|
: $t('trials:adReview:table:view')
|
||||||
"
|
" width="200" :fixed="isFixed ? 'right' : false">
|
||||||
width="200"
|
|
||||||
:fixed="isFixed ? 'right' : false"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 查看R1详情 -->
|
<!-- 查看R1详情 -->
|
||||||
<el-button
|
<el-button type="text" :title="$t('trials:adReview:table:viewR1')" @click="handleView(scope.row, 1)">
|
||||||
type="text"
|
|
||||||
:title="$t('trials:adReview:table:viewR1')"
|
|
||||||
@click="handleView(scope.row, 1)"
|
|
||||||
>
|
|
||||||
R1
|
R1
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 查看R2详情 -->
|
<!-- 查看R2详情 -->
|
||||||
<el-button
|
<el-button type="text" :title="$t('trials:adReview:table:viewR2')" @click="handleView(scope.row, 2)">
|
||||||
type="text"
|
|
||||||
:title="$t('trials:adReview:table:viewR2')"
|
|
||||||
@click="handleView(scope.row, 2)"
|
|
||||||
>
|
|
||||||
R2
|
R2
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<!-- 全局详情 PCWG -->
|
<!-- 全局详情 PCWG -->
|
||||||
<el-table-column
|
<el-table-column v-if="criterionType === 10" prop="VisitName" :label="$t('trials:adReview:table:glInfo')"
|
||||||
v-if="criterionType === 10"
|
show-overflow-tooltip width="150">
|
||||||
prop="VisitName"
|
|
||||||
:label="$t('trials:adReview:table:glInfo')"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="150"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 查看R1详情 -->
|
<!-- 查看R1详情 -->
|
||||||
<el-button
|
<el-button v-if="scope.$index === adInfo.VisitInfoList.length - 1" type="text"
|
||||||
v-if="scope.$index === adInfo.VisitInfoList.length - 1"
|
:title="$t('trials:adReview:table:viewR1')" @click="handleViewGl(scope.row, 1)">
|
||||||
type="text"
|
|
||||||
:title="$t('trials:adReview:table:viewR1')"
|
|
||||||
@click="handleViewGl(scope.row, 1)"
|
|
||||||
>
|
|
||||||
R1
|
R1
|
||||||
</el-button>
|
</el-button>
|
||||||
<!-- 查看R2详情 -->
|
<!-- 查看R2详情 -->
|
||||||
<el-button
|
<el-button v-if="scope.$index === adInfo.VisitInfoList.length - 1" type="text"
|
||||||
v-if="scope.$index === adInfo.VisitInfoList.length - 1"
|
:title="$t('trials:adReview:table:viewR2')" @click="handleViewGl(scope.row, 2)">
|
||||||
type="text"
|
|
||||||
:title="$t('trials:adReview:table:viewR2')"
|
|
||||||
@click="handleViewGl(scope.row, 2)"
|
|
||||||
>
|
|
||||||
R2
|
R2
|
||||||
</el-button>
|
</el-button>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -186,120 +136,64 @@
|
||||||
$t("trials:adReview:title:adResult")
|
$t("trials:adReview:title:adResult")
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<el-form
|
<el-form ref="adForm" v-loading="loading" :model="adForm" style="width: 800px" label-width="100">
|
||||||
ref="adForm"
|
|
||||||
v-loading="loading"
|
|
||||||
:model="adForm"
|
|
||||||
style="width: 800px"
|
|
||||||
label-width="100"
|
|
||||||
>
|
|
||||||
<!-- 选择阅片人 -->
|
<!-- 选择阅片人 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('trials:adReview:title:choseReader')" prop="judgeResultTaskId" :rules="[
|
||||||
:label="$t('trials:adReview:title:choseReader')"
|
|
||||||
prop="judgeResultTaskId"
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: this.$t('common:ruleMessage:select') },
|
{ required: true, message: this.$t('common:ruleMessage:select') },
|
||||||
]"
|
]">
|
||||||
>
|
<el-radio-group v-model="adForm.judgeResultTaskId" :disabled="adInfo.ReadingTaskState >= 2">
|
||||||
<el-radio-group
|
<el-radio v-for="t in visitTaskArmList" :key="t.VisitTaskId" :label="t.VisitTaskId"
|
||||||
v-model="adForm.judgeResultTaskId"
|
@change="handleVisitTaskArmChange">
|
||||||
:disabled="adInfo.ReadingTaskState >= 2"
|
|
||||||
>
|
|
||||||
<el-radio
|
|
||||||
v-for="t in visitTaskArmList"
|
|
||||||
:key="t.VisitTaskId"
|
|
||||||
:label="t.VisitTaskId"
|
|
||||||
@change="handleVisitTaskArmChange"
|
|
||||||
>
|
|
||||||
{{ $fd("ArmEnum", t.ArmEnum) }}
|
{{ $fd("ArmEnum", t.ArmEnum) }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 裁判原因 -->
|
<!-- 裁判原因 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('trials:adReview:title:adReason')" prop="judgeResultRemark" :rules="[
|
||||||
:label="$t('trials:adReview:title:adReason')"
|
|
||||||
prop="judgeResultRemark"
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: this.$t('common:ruleMessage:specify') },
|
{ required: true, message: this.$t('common:ruleMessage:specify') },
|
||||||
{
|
{
|
||||||
max: 500,
|
max: 500,
|
||||||
message: `${this.$t('common:ruleMessage:maxLength')} 500`,
|
message: `${this.$t('common:ruleMessage:maxLength')} 500`,
|
||||||
trigger: ['blur', 'change'],
|
trigger: ['blur', 'change'],
|
||||||
},
|
},
|
||||||
]"
|
]">
|
||||||
>
|
|
||||||
<div style="position: relative">
|
<div style="position: relative">
|
||||||
<div
|
<div style="
|
||||||
style="
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 0;
|
left: 0;
|
||||||
top: 30px;
|
top: 30px;
|
||||||
color: #606266;
|
color: #606266;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ remark }}
|
{{ remark }}
|
||||||
</div>
|
</div>
|
||||||
<el-input
|
<el-input v-model="adForm.judgeResultRemark" type="textarea" :autosize="{ minRows: 4, maxRows: 6 }"
|
||||||
v-model="adForm.judgeResultRemark"
|
:disabled="adInfo.ReadingTaskState >= 2" style="margin-top: 25px" />
|
||||||
type="textarea"
|
|
||||||
:autosize="{ minRows: 4, maxRows: 6 }"
|
|
||||||
:disabled="adInfo.ReadingTaskState >= 2"
|
|
||||||
style="margin-top: 25px"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 截图说明 -->
|
<!-- 截图说明 -->
|
||||||
<el-form-item :label="$t('trials:adReview:title:screenShot')">
|
<el-form-item :label="$t('trials:adReview:title:screenShot')">
|
||||||
<el-upload
|
<el-upload action :accept="accept" :on-preview="handlePictureCardPreview" :before-upload="handleBeforeUpload"
|
||||||
action
|
:http-request="uploadScreenshot" list-type="picture-card" :on-remove="handleRemove" :file-list="fileList"
|
||||||
:accept="accept"
|
:class="{ disabled: adInfo.ReadingTaskState >= 2 }" :disabled="adInfo.ReadingTaskState >= 2">
|
||||||
:on-preview="handlePictureCardPreview"
|
|
||||||
:before-upload="handleBeforeUpload"
|
|
||||||
:http-request="uploadScreenshot"
|
|
||||||
list-type="picture-card"
|
|
||||||
:on-remove="handleRemove"
|
|
||||||
:file-list="fileList"
|
|
||||||
:class="{ disabled: adInfo.ReadingTaskState >= 2 }"
|
|
||||||
:disabled="adInfo.ReadingTaskState >= 2"
|
|
||||||
>
|
|
||||||
<i slot="default" class="el-icon-plus" />
|
<i slot="default" class="el-icon-plus" />
|
||||||
<div
|
<div slot="file" slot-scope="{ file }" style="width: 100%; height: 100%">
|
||||||
slot="file"
|
<viewer :ref="file.url" :images="images" style="
|
||||||
slot-scope="{ file }"
|
|
||||||
style="width: 100%; height: 100%"
|
|
||||||
>
|
|
||||||
<viewer
|
|
||||||
:ref="file.url"
|
|
||||||
:images="images"
|
|
||||||
style="
|
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
"
|
">
|
||||||
>
|
<img class="el-upload-list__item-thumbnail" :src="OSSclientConfig.basePath + file.url" alt=""
|
||||||
<img
|
crossorigin="anonymous" style="max-width: 100%; max-height: 100%">
|
||||||
class="el-upload-list__item-thumbnail"
|
|
||||||
:src="OSSclientConfig.basePath + file.url"
|
|
||||||
alt=""
|
|
||||||
crossorigin="anonymous"
|
|
||||||
style="max-width: 100%; max-height: 100%"
|
|
||||||
>
|
|
||||||
<span class="el-upload-list__item-actions">
|
<span class="el-upload-list__item-actions">
|
||||||
<span
|
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
|
||||||
class="el-upload-list__item-preview"
|
|
||||||
@click="handlePictureCardPreview(file)"
|
|
||||||
>
|
|
||||||
<i class="el-icon-zoom-in" />
|
<i class="el-icon-zoom-in" />
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span
|
<span v-if="adInfo.ReadingTaskState < 2" class="el-upload-list__item-delete"
|
||||||
v-if="adInfo.ReadingTaskState < 2"
|
@click="handleRemove(file)">
|
||||||
class="el-upload-list__item-delete"
|
|
||||||
@click="handleRemove(file)"
|
|
||||||
>
|
|
||||||
<i class="el-icon-delete" />
|
<i class="el-icon-delete" />
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -324,10 +218,7 @@
|
||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
|
|
||||||
<el-card
|
<el-card v-if="isReadingShowPreviousResults" :body-style="{ padding: '10px' }">
|
||||||
v-if="isReadingShowPreviousResults"
|
|
||||||
:body-style="{ padding: '10px' }"
|
|
||||||
>
|
|
||||||
<div slot="header" class="clearfix">
|
<div slot="header" class="clearfix">
|
||||||
<!-- 既往裁判评估 -->
|
<!-- 既往裁判评估 -->
|
||||||
<span style="font-weight: bold">{{
|
<span style="font-weight: bold">{{
|
||||||
|
|
@ -335,24 +226,12 @@
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<el-table
|
<el-table v-loading="priorLoading" :data="priorADList" style="width: 100%">
|
||||||
v-loading="priorLoading"
|
|
||||||
:data="priorADList"
|
|
||||||
style="width: 100%"
|
|
||||||
>
|
|
||||||
<!-- 裁判阅片 -->
|
<!-- 裁判阅片 -->
|
||||||
<el-table-column
|
<el-table-column prop="TaskBlindName" :label="$t('trials:adReview:table:adReading')" show-overflow-tooltip
|
||||||
prop="TaskBlindName"
|
width="200" />
|
||||||
:label="$t('trials:adReview:table:adReading')"
|
<el-table-column prop="JudgeResultArm" :label="$t('trials:adReview:table:adResult')" show-overflow-tooltip
|
||||||
show-overflow-tooltip
|
width="200">
|
||||||
width="200"
|
|
||||||
/>
|
|
||||||
<el-table-column
|
|
||||||
prop="JudgeResultArm"
|
|
||||||
:label="$t('trials:adReview:table:adResult')"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="200"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ $fd("ArmEnum", scope.row.JudgeResultArm) }}
|
{{ $fd("ArmEnum", scope.row.JudgeResultArm) }}
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -360,35 +239,22 @@
|
||||||
<el-table-column :label="$t('common:action:action')" width="200">
|
<el-table-column :label="$t('common:action:action')" width="200">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 查看详情 -->
|
<!-- 查看详情 -->
|
||||||
<el-button
|
<el-button circle :title="$t('trials:adReview:table:view')" icon="el-icon-view"
|
||||||
circle
|
@click="handleViewDetail(scope.row.VisitTaskId)" />
|
||||||
:title="$t('trials:adReview:table:view')"
|
|
||||||
icon="el-icon-view"
|
|
||||||
@click="handleViewDetail(scope.row.VisitTaskId)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
</el-card>
|
</el-card>
|
||||||
<!-- 签名框 -->
|
<!-- 签名框 -->
|
||||||
<el-dialog
|
<el-dialog v-if="signVisible" :visible.sync="signVisible" :close-on-click-modal="false" width="600px"
|
||||||
v-if="signVisible"
|
custom-class="base-dialog-wrapper">
|
||||||
:visible.sync="signVisible"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
width="600px"
|
|
||||||
custom-class="base-dialog-wrapper"
|
|
||||||
>
|
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
<span style="font-size: 18px">{{ $t("common:dialogTitle:sign") }}</span>
|
<span style="font-size: 18px">{{ $t("common:dialogTitle:sign") }}</span>
|
||||||
<span style="font-size: 12px; margin-left: 5px">{{
|
<span style="font-size: 12px; margin-left: 5px">{{
|
||||||
`(${$t("common:label:sign")}${currentUser})`
|
`(${$t("common:label:sign")}${currentUser})`
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<SignForm
|
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||||
ref="signForm"
|
|
||||||
:sign-code-enum="signCode"
|
|
||||||
@closeDialog="closeSignDialog"
|
|
||||||
/>
|
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -729,17 +595,13 @@ export default {
|
||||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId
|
||||||
this.trialId
|
}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
|
||||||
this.subjectId
|
|
||||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId
|
||||||
this.trialId
|
}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
|
||||||
this.subjectId
|
|
||||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
}
|
}
|
||||||
var routeData = this.$router.resolve({ path })
|
var routeData = this.$router.resolve({ path })
|
||||||
|
|
@ -766,21 +628,15 @@ export default {
|
||||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId
|
||||||
this.trialId
|
}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&visitTaskId=${task.VisitTaskId
|
||||||
this.subjectId
|
|
||||||
}&visitTaskId=${
|
|
||||||
task.VisitTaskId
|
|
||||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId
|
||||||
this.trialId
|
}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&visitTaskId=${task.VisitTaskId
|
||||||
this.subjectId
|
|
||||||
}&visitTaskId=${
|
|
||||||
task.VisitTaskId
|
|
||||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
}
|
}
|
||||||
var routeData = this.$router.resolve({ path })
|
var routeData = this.$router.resolve({ path })
|
||||||
|
|
@ -801,21 +657,15 @@ export default {
|
||||||
this.$router.currentRoute.query.TrialReadingCriterionId
|
this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
|
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId
|
||||||
this.trialId
|
}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&visitTaskId=${task.GlobalVisitTaskId
|
||||||
this.subjectId
|
|
||||||
}&visitTaskId=${
|
|
||||||
task.GlobalVisitTaskId
|
|
||||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId
|
||||||
this.trialId
|
}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId
|
||||||
}&subjectCode=${this.subjectCode}&subjectId=${
|
}&visitTaskId=${task.GlobalVisitTaskId
|
||||||
this.subjectId
|
|
||||||
}&visitTaskId=${
|
|
||||||
task.GlobalVisitTaskId
|
|
||||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
}
|
}
|
||||||
var routeData = this.$router.resolve({ path })
|
var routeData = this.$router.resolve({ path })
|
||||||
|
|
@ -932,17 +782,21 @@ export default {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
|
|
||||||
.box-mr {
|
.box-mr {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.disabled {
|
.disabled {
|
||||||
::v-deep .el-upload--picture-card {
|
::v-deep .el-upload--picture-card {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-upload-list__item {
|
::v-deep .el-upload-list__item {
|
||||||
transition: none !important;
|
transition: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-upload-list__item-thumbnail {
|
::v-deep .el-upload-list__item-thumbnail {
|
||||||
/* 图片在方框内显示长边 */
|
/* 图片在方框内显示长边 */
|
||||||
object-fit: scale-down !important;
|
object-fit: scale-down !important;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,116 @@
|
||||||
|
<template>
|
||||||
|
<div class="ContourViewport" ref="ContourViewport" id="ContourViewport"></div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getRenderingEngine,
|
||||||
|
CONSTANTS,
|
||||||
|
setVolumesForViewports,
|
||||||
|
eventTarget,
|
||||||
|
Enums,
|
||||||
|
utilities,
|
||||||
|
} from '@cornerstonejs/core'
|
||||||
|
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||||
|
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||||
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
|
const {
|
||||||
|
Enums: csToolsEnums,
|
||||||
|
segmentation,
|
||||||
|
TrackballRotateTool,
|
||||||
|
ToolGroupManager
|
||||||
|
} = cornerstoneTools
|
||||||
|
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||||
|
export default {
|
||||||
|
name: "ContourViewport",
|
||||||
|
props: {
|
||||||
|
renderingEngineId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
viewportId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
visitInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// visible: {
|
||||||
|
// type: Boolean,
|
||||||
|
// default: false
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
volumeId: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
eventTarget.addEventListener(Enums.Events.WEB_WORKER_PROGRESS, (evt) => {
|
||||||
|
const { progress } = evt.detail;
|
||||||
|
console.log(progress, 'countour_progress')
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async setSeriesInfo(obj) {
|
||||||
|
try {
|
||||||
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
|
let { volumeId, segmentationId } = obj
|
||||||
|
this.volumeId = volumeId
|
||||||
|
await setVolumesForViewports(
|
||||||
|
renderingEngine,
|
||||||
|
[{ volumeId, callback: setCtTransferFunctionForVolumeActor }],
|
||||||
|
[this.viewportId]
|
||||||
|
);
|
||||||
|
// const volumeActor = viewport.getDefaultActor()
|
||||||
|
// .actor;
|
||||||
|
// utilities.applyPreset(
|
||||||
|
// volumeActor,
|
||||||
|
// CONSTANTS.VIEWPORT_PRESETS.find((preset) => preset.name === 'CT-Bone')
|
||||||
|
// );
|
||||||
|
// volumeActor.setVisibility(false);
|
||||||
|
viewport.render();
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(this.viewportId)
|
||||||
|
toolGroup.setToolActive(TrackballRotateTool.toolName, {
|
||||||
|
bindings: [
|
||||||
|
{
|
||||||
|
mouseButton: MouseBindings.Primary,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
let s = segmentation.getActiveSegmentation(this.viewportId)
|
||||||
|
if (s) {
|
||||||
|
await segmentation.removeSegmentationRepresentation(this.viewportId, {
|
||||||
|
segmentationId: s.segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Surface,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
console.log("ContourLoading...")
|
||||||
|
await segmentation.addSegmentationRepresentations(this.viewportId, [
|
||||||
|
{
|
||||||
|
segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Contour,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#ContourViewport {
|
||||||
|
width: 450px;
|
||||||
|
height: 300px;
|
||||||
|
position: fixed;
|
||||||
|
top: 100px;
|
||||||
|
z-index: -9999;
|
||||||
|
left: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -76,9 +76,24 @@ import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||||
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
|
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
|
||||||
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||||
import { setCtMappingRange } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
import { setCtMappingRange } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||||
import { setPetColorMapTransferFunctionForVolumeActor } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetColorMapTransferFunctionForVolumeActor'
|
import {
|
||||||
|
setPetTransferFunctionForVolumeActor
|
||||||
|
} from './helpers/index.js'
|
||||||
import { vec3, mat4 } from 'gl-matrix'
|
import { vec3, mat4 } from 'gl-matrix'
|
||||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
|
import {
|
||||||
|
renderSegmentation,
|
||||||
|
readingSegmentByConfig,
|
||||||
|
selectSegmentation,
|
||||||
|
selectSegment,
|
||||||
|
createSegmentationRepresentation,
|
||||||
|
viewSegmentation,
|
||||||
|
viewSegment,
|
||||||
|
jumpBidirectional,
|
||||||
|
viewBidirectional,
|
||||||
|
changeColor,
|
||||||
|
resetViewport
|
||||||
|
} from "./helpers/segmentations"
|
||||||
export default {
|
export default {
|
||||||
name: 'MPRViewport',
|
name: 'MPRViewport',
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -99,6 +114,36 @@ export default {
|
||||||
default: () => {
|
default: () => {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
histogramVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
actionConfiguration: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SegmentConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
curSegSeries: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
segmentIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
segmentationId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -140,6 +185,7 @@ export default {
|
||||||
rotateAngle: 0,
|
rotateAngle: 0,
|
||||||
rotateBarLeft: 0,
|
rotateBarLeft: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
toggleClipPlayTimer: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -149,6 +195,39 @@ export default {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.initViewport()
|
this.initViewport()
|
||||||
})
|
})
|
||||||
|
DicomEvent.$on('createSegmentationRepresentation', (segmentationId) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
createSegmentationRepresentation(this.viewportId, segmentationId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('viewSegmentation', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
viewSegmentation(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('viewSegment', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
viewSegment(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('jumpBidirectional', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
jumpBidirectional(obj, this.viewportId, this.volumeId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('viewBidirectional', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
viewBidirectional(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('changeColor', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
changeColor(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('resetViewport', () => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
resetViewport(this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('renderSegmentation', async (viewportId) => {
|
||||||
|
// if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
|
if (this.viewportId !== viewportId) return false
|
||||||
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
MPRInfo: {
|
MPRInfo: {
|
||||||
|
|
@ -167,6 +246,25 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
|
},
|
||||||
|
SegmentConfig: {
|
||||||
|
handler() {
|
||||||
|
if (!this.segmentationId) return false
|
||||||
|
if (!this.series.TaskInfo) return false
|
||||||
|
readingSegmentByConfig(this.series, this.series.TaskInfo, this.viewportId, this.segmentationId, this.SegmentConfig)
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
segmentIndex() {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
|
if (this.segmentIndex <= 0) return false
|
||||||
|
selectSegment(this.viewportId, this.segmentationId, this.segmentIndex)
|
||||||
|
},
|
||||||
|
segmentationId() {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
|
if (!this.segmentationId) return false
|
||||||
|
selectSegmentation(this.viewportId, this.segmentationId)
|
||||||
|
readingSegmentByConfig(this.series, this.series.TaskInfo, this.viewportId, this.segmentationId, this.SegmentConfig)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -183,6 +281,7 @@ export default {
|
||||||
this.element.addEventListener("CORNERSTONE_VOLUME_NEW_IMAGE", this.stackNewImage)
|
this.element.addEventListener("CORNERSTONE_VOLUME_NEW_IMAGE", this.stackNewImage)
|
||||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||||
this.element.addEventListener('wheel', (e) => {
|
this.element.addEventListener('wheel', (e) => {
|
||||||
|
// if (this.histogramVisible) return false
|
||||||
// console.log('CORNERSTONE_STACK_VIEWPORT_SCROLL')
|
// console.log('CORNERSTONE_STACK_VIEWPORT_SCROLL')
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
|
|
@ -285,6 +384,7 @@ export default {
|
||||||
this.imageInfo.sliceThickness = type === this.series.orientation ? spacing[2] : spacing[0]
|
this.imageInfo.sliceThickness = type === this.series.orientation ? spacing[2] : spacing[0]
|
||||||
this.imageInfo.total = detail.numberOfSlices
|
this.imageInfo.total = detail.numberOfSlices
|
||||||
this.getOrientationMarker()
|
this.getOrientationMarker()
|
||||||
|
this.$emit("resetHistogram")
|
||||||
let properties = viewport.getProperties(this.volumeId)
|
let properties = viewport.getProperties(this.volumeId)
|
||||||
if (properties && properties.voiRange) {
|
if (properties && properties.voiRange) {
|
||||||
var { lower, upper } = properties.voiRange
|
var { lower, upper } = properties.voiRange
|
||||||
|
|
@ -392,11 +492,20 @@ export default {
|
||||||
this.playClipState = isPlay
|
this.playClipState = isPlay
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
|
|
||||||
if (isPlay) {
|
if (isPlay) {
|
||||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
|
this.toggleClipPlayTimer = setInterval(() => {
|
||||||
|
let index = this.series.SliceIndex + 1;
|
||||||
|
if (index > this.imageInfo.total - 1) index = 0
|
||||||
|
csUtils.jumpToSlice(viewport.element, { imageIndex: index });
|
||||||
|
|
||||||
|
}, framesPerSecond)
|
||||||
|
// cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
|
||||||
} else {
|
} else {
|
||||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
if (this.toggleClipPlayTimer) {
|
||||||
|
clearInterval(this.toggleClipPlayTimer)
|
||||||
|
this.toggleClipPlayTimer = null
|
||||||
|
}
|
||||||
|
// cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollPage(type) {
|
scrollPage(type) {
|
||||||
|
|
@ -490,7 +599,7 @@ export default {
|
||||||
.setVolumes([{
|
.setVolumes([{
|
||||||
volumeId: this.volumeId, callback: (r) => {
|
volumeId: this.volumeId, callback: (r) => {
|
||||||
if (this.series.Modality === 'PT') {
|
if (this.series.Modality === 'PT') {
|
||||||
setPetColorMapTransferFunctionForVolumeActor(r, true)
|
setPetTransferFunctionForVolumeActor(r)
|
||||||
} else {
|
} else {
|
||||||
let volume = cache.getVolume(this.volumeId)
|
let volume = cache.getVolume(this.volumeId)
|
||||||
const voi = metaData.get('voiLutModule', volume._imageIds[Math.ceil((volume._imageIds.length - 1) / 2)])
|
const voi = metaData.get('voiLutModule', volume._imageIds[Math.ceil((volume._imageIds.length - 1) / 2)])
|
||||||
|
|
@ -498,7 +607,6 @@ export default {
|
||||||
setCtTransferFunctionForVolumeActor(r)
|
setCtTransferFunctionForVolumeActor(r)
|
||||||
}
|
}
|
||||||
console.log("渲染成功")
|
console.log("渲染成功")
|
||||||
DicomEvent.$emit("isloaded", { isChange: false })
|
|
||||||
}
|
}
|
||||||
}]).then(r => {
|
}]).then(r => {
|
||||||
if (data.isLocation || !this.imageInfo.zoom) {
|
if (data.isLocation || !this.imageInfo.zoom) {
|
||||||
|
|
@ -506,6 +614,22 @@ export default {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
viewport.render()
|
viewport.render()
|
||||||
|
if (this.series.Modality === 'PT') {
|
||||||
|
setTimeout(() => {
|
||||||
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
|
viewport.resetProperties()
|
||||||
|
viewport.setProperties({ voiRange: { upper: 5, lower: 0 } })
|
||||||
|
viewport.render()
|
||||||
|
renderingEngine.render()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration)
|
||||||
|
DicomEvent.$emit('SegmentationLoading', this.viewportId)
|
||||||
|
let volume = cache.getVolume(this.volumeId)
|
||||||
|
// console.log(volume, 'volume')
|
||||||
|
if (this.series.orientation === 'AXIAL' && this.series.curIndex) return this.setFullScreen(this.series.curIndex)
|
||||||
|
let index = this.series.orientation === 'AXIAL' ? Math.ceil((volume._imageIds.length - 1) / 2) - 1 : Math.ceil((volume.dimensions[0]) / 2) - 1
|
||||||
|
this.setFullScreen(index)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
@ -680,6 +804,12 @@ export default {
|
||||||
return `NS: ${this.$store.state.trials.downloadTip}`
|
return `NS: ${this.$store.state.trials.downloadTip}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
destroyed() {
|
||||||
|
if (this.toggleClipPlayTimer) {
|
||||||
|
clearInterval(this.toggleClipPlayTimer)
|
||||||
|
this.toggleClipPlayTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -123,6 +123,10 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
activeTool: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -254,10 +258,15 @@ export default {
|
||||||
this.defaultWindowLevel.windowCenter = windowCenter
|
this.defaultWindowLevel.windowCenter = windowCenter
|
||||||
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
this.imageInfo.wwwc = `${Math.round(windowWidth)}/${Math.round(windowCenter)}`
|
||||||
}
|
}
|
||||||
const toolGroupId = this.viewportId
|
const toolGroup =
|
||||||
const toolGroup = cornerstoneTools.ToolGroupManager.getToolGroup(toolGroupId)
|
cornerstoneTools.ToolGroupManager.getToolGroupForViewport(
|
||||||
|
this.viewportId,
|
||||||
|
this.renderingEngineId
|
||||||
|
) || cornerstoneTools.ToolGroupManager.getToolGroup(this.viewportId)
|
||||||
|
if (toolGroup) {
|
||||||
toolGroup.setToolEnabled('ScaleOverlay')
|
toolGroup.setToolEnabled('ScaleOverlay')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
setFullScreen(index) {
|
setFullScreen(index) {
|
||||||
|
|
@ -829,6 +838,7 @@ export default {
|
||||||
this.sliderInfo.isMove = false
|
this.sliderInfo.isMove = false
|
||||||
},
|
},
|
||||||
handletoolsMouseWheel(e) {
|
handletoolsMouseWheel(e) {
|
||||||
|
if (this.activeTool === 'Crosshairs') return
|
||||||
const { viewportId, wheel } = e.detail
|
const { viewportId, wheel } = e.detail
|
||||||
if (this.isMip) {
|
if (this.isMip) {
|
||||||
const container = document.getElementById('rotateBar')
|
const container = document.getElementById('rotateBar')
|
||||||
|
|
@ -852,6 +862,7 @@ export default {
|
||||||
this.rotateBarInfo.isMove = false
|
this.rotateBarInfo.isMove = false
|
||||||
},
|
},
|
||||||
rotateBarMousemove(e) {
|
rotateBarMousemove(e) {
|
||||||
|
if (this.activeTool === 'Crosshairs') return
|
||||||
// 滚动旋转
|
// 滚动旋转
|
||||||
if (!this.rotateBarInfo.isMove) return
|
if (!this.rotateBarInfo.isMove) return
|
||||||
const container = document.getElementById('rotateBar')
|
const container = document.getElementById('rotateBar')
|
||||||
|
|
@ -867,6 +878,7 @@ export default {
|
||||||
this.rotateBarLeft = x
|
this.rotateBarLeft = x
|
||||||
},
|
},
|
||||||
rotateBarMousedown(e) {
|
rotateBarMousedown(e) {
|
||||||
|
if (this.activeTool === 'Crosshairs') return
|
||||||
this.rotateBarInfo.initLeft = e.srcElement.offsetLeft
|
this.rotateBarInfo.initLeft = e.srcElement.offsetLeft
|
||||||
this.rotateBarInfo.initX = e.clientX
|
this.rotateBarInfo.initX = e.clientX
|
||||||
this.rotateBarInfo.isMove = true
|
this.rotateBarInfo.isMove = true
|
||||||
|
|
@ -905,6 +917,7 @@ export default {
|
||||||
viewport.render()
|
viewport.render()
|
||||||
},
|
},
|
||||||
clickRotate(e) {
|
clickRotate(e) {
|
||||||
|
if (this.activeTool === 'Crosshairs') return
|
||||||
// console.log('clickRotate')
|
// console.log('clickRotate')
|
||||||
const container = document.getElementById('rotateBar')
|
const container = document.getElementById('rotateBar')
|
||||||
const containerWidth = container.offsetWidth
|
const containerWidth = container.offsetWidth
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,8 @@
|
||||||
<div v-for="s in visitTaskList" v-show="activeTaskId === s.VisitTaskId" :key="s.VisitTaskId"
|
<div v-for="s in visitTaskList" v-show="activeTaskId === s.VisitTaskId" :key="s.VisitTaskId"
|
||||||
style="height:100%;">
|
style="height:100%;">
|
||||||
<study-list v-if="selectArr.includes(s.VisitTaskId) && s.StudyList.length > 0" :ref="s.VisitTaskId"
|
<study-list v-if="selectArr.includes(s.VisitTaskId) && s.StudyList.length > 0" :ref="s.VisitTaskId"
|
||||||
:visit-task-info="s" :marked-series-ids="markedSeriesIds" @activeSeries="activeSeries"
|
:visit-task-info="s" :marked-series-ids="markedSeriesIds" :readingTool="readingTool"
|
||||||
@showMultiFrame="showMultiFrame" />
|
@activeSeries="activeSeries" @showMultiFrame="showMultiFrame" />
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -165,6 +165,11 @@
|
||||||
v-if="(criterionType === 0 && readingTool === 0) || this.readingTool === 3">
|
v-if="(criterionType === 0 && readingTool === 0) || this.readingTool === 3">
|
||||||
<svg-icon icon-class="mpr" class="svg-icon" style="transform: rotate(180deg);" />
|
<svg-icon icon-class="mpr" class="svg-icon" style="transform: rotate(180deg);" />
|
||||||
</div>
|
</div>
|
||||||
|
<!-- 直方图 -->
|
||||||
|
<div class="tool-item" :title="`${$t('trials:reading:button:histogram')}`" @click.prevent="openHistogram"
|
||||||
|
v-if="this.readingTool === 3">
|
||||||
|
<svg-icon icon-class="histogram" class="svg-icon" />
|
||||||
|
</div>
|
||||||
<!-- 十字准星 -->
|
<!-- 十字准星 -->
|
||||||
<div :class="['tool-item', activeTool === 'Crosshairs' ? 'tool-item-active' : '']" v-if="isMPR"
|
<div :class="['tool-item', activeTool === 'Crosshairs' ? 'tool-item-active' : '']" v-if="isMPR"
|
||||||
:title="$t('trials:reading:button:crosshairs')" @click.prevent="setToolActive('Crosshairs')">
|
:title="$t('trials:reading:button:crosshairs')" @click.prevent="setToolActive('Crosshairs')">
|
||||||
|
|
@ -175,6 +180,11 @@
|
||||||
@click.prevent="openFusion">
|
@click.prevent="openFusion">
|
||||||
<svg-icon icon-class="fusion" class="svg-icon" />
|
<svg-icon icon-class="fusion" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
|
<div :class="['tool-item', activeTool === 'Crosshairs' ? 'tool-item-active' : '']"
|
||||||
|
v-if="readingTool === 2 && isFusion" :title="$t('trials:reading:button:crosshairs')"
|
||||||
|
@click.prevent="setToolActive('Crosshairs')">
|
||||||
|
<svg-icon icon-class="crosshairs" class="svg-icon" />
|
||||||
|
</div>
|
||||||
<div v-for="tool in tools" :key="tool.toolName"
|
<div v-for="tool in tools" :key="tool.toolName"
|
||||||
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === tool.toolName ? 'tool-item-active' : '']"
|
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === tool.toolName ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: tool.isDisabled ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: tool.isDisabled ? 'not-allowed' : 'pointer' }"
|
||||||
|
|
@ -308,8 +318,13 @@
|
||||||
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
||||||
<VolumeViewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
<VolumeViewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
||||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
||||||
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
:histogramVisible="histogramVisible" :actionConfiguration="actionConfiguration"
|
||||||
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" v-if="readingTool === 3" />
|
:SegmentConfig="SegmentConfig" :segmentationId.sync="segId" :segmentIndex.sync="segIndex"
|
||||||
|
:curSegSeries.sync="curSegSeries" @activeViewport="activeViewport"
|
||||||
|
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||||
|
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup"
|
||||||
|
@resetViewport="resetViewport" @resetHistogram="resetHistogram" v-if="readingTool === 3"
|
||||||
|
v-resize="(e) => handleSizeChange(e, `viewport-${index}`)" />
|
||||||
<Viewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
<Viewport :ref="`viewport-${index}`" :data-viewport-uid="`viewport-${index}`"
|
||||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-${index}`" :viewport-index="index"
|
||||||
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
@activeViewport="activeViewport" @toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||||
|
|
@ -325,9 +340,13 @@
|
||||||
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
||||||
<MPRViewport :ref="`viewport-MPR-${index}`" :data-viewport-uid="`viewport-MPR-${index}`"
|
<MPRViewport :ref="`viewport-MPR-${index}`" :data-viewport-uid="`viewport-MPR-${index}`"
|
||||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-MPR-${index}`"
|
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-MPR-${index}`"
|
||||||
:viewport-index="index" :MPRInfo="MPRInfo" @activeViewport="activeViewport" @setMPRInfo="setMPRInfo"
|
:viewport-index="index" :histogramVisible="histogramVisible"
|
||||||
|
:actionConfiguration="actionConfiguration" :SegmentConfig="SegmentConfig"
|
||||||
|
:segmentationId.sync="segId" :segmentIndex.sync="segIndex" :curSegSeries.sync="curSegSeries"
|
||||||
|
:MPRInfo="MPRInfo" @activeViewport="activeViewport" @setMPRInfo="setMPRInfo"
|
||||||
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||||
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup" />
|
@renderAnnotations="renderAnnotations" @contentMouseup="contentMouseup"
|
||||||
|
@resetHistogram="resetHistogram" v-resize="(e) => handleSizeChange(e, `viewport-MPR-${index}`)" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="readingTool === 2"
|
<div v-if="readingTool === 2"
|
||||||
|
|
@ -335,15 +354,19 @@
|
||||||
:style="gridStyle">
|
:style="gridStyle">
|
||||||
<div v-for="(v, index) in cellsMax" v-show="index < cells.length" :key="`viewport-fusion-${index}`"
|
<div v-for="(v, index) in cellsMax" v-show="index < cells.length" :key="`viewport-fusion-${index}`"
|
||||||
:class="['grid-cell', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
:class="['grid-cell', index === activeViewportIndex ? 'cell_active' : '', index === fullScreenIndex ? 'cell-full-screen' : '']"
|
||||||
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)">
|
@dblclick="toggleFullScreen($event, index)" @click="activeViewport(index)"
|
||||||
|
@mouseenter="hoverFusionViewport(index)" @mouseleave="hoverFusionViewport(-1)">
|
||||||
<PetCtViewport :ref="`viewport-fusion-${index}`" :data-viewport-uid="`viewport-fusion-${index}`"
|
<PetCtViewport :ref="`viewport-fusion-${index}`" :data-viewport-uid="`viewport-fusion-${index}`"
|
||||||
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-fusion-${index}`"
|
:rendering-engine-id="renderingEngineId" :viewport-id="`viewport-fusion-${index}`"
|
||||||
:viewport-index="index" @activeViewport="activeViewport"
|
:viewport-index="index" :active-tool="activeTool" @activeViewport="activeViewport"
|
||||||
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
@toggleTaskByViewport="toggleTaskByViewport" @previewCD="previewCD"
|
||||||
@renderAnnotations="renderAnnotations" @upperRangeChange="upperRangeChange"
|
@renderAnnotations="renderAnnotations" @upperRangeChange="upperRangeChange"
|
||||||
@contentMouseup="contentMouseup" />
|
@contentMouseup="contentMouseup" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="readingTool === 2" class="fusion-hidden-viewports">
|
||||||
|
<div ref="viewport-fusion-hidden-sag" class="fusion-hidden-viewport" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- 表单 -->
|
<!-- 表单 -->
|
||||||
|
|
@ -352,9 +375,11 @@
|
||||||
<el-tab-pane :label="$t('trials:reading:dicom3D:tabs:segment')" name="segment">
|
<el-tab-pane :label="$t('trials:reading:dicom3D:tabs:segment')" name="segment">
|
||||||
<Segmentations ref="Segmentations" :visitInfo="taskInfo" :isMPR="isMPR"
|
<Segmentations ref="Segmentations" :visitInfo="taskInfo" :isMPR="isMPR"
|
||||||
:volumeToolGroupId="volumeToolGroupId" :viewportKey="viewportKey" :global-loading.sync="loading"
|
:volumeToolGroupId="volumeToolGroupId" :viewportKey="viewportKey" :global-loading.sync="loading"
|
||||||
:loadingText.sync="loadingText" :rendering-engine-id="renderingEngineId"
|
:trialCriterion="trialCriterion" :loadingText.sync="loadingText"
|
||||||
:activeViewportIndex="activeViewportIndex" :activeTool.sync="activeTool"
|
:rendering-engine-id="renderingEngineId" :SegmentConfig="SegmentConfig" :segId.sync="segId"
|
||||||
:actionConfiguration="actionConfiguration" @setToolsPassive="setToolsPassive"
|
:segIndex.sync="segIndex" :curSegSeries.sync="curSegSeries" :activeViewportIndex="activeViewportIndex"
|
||||||
|
:activeTool.sync="activeTool" :actionConfiguration="actionConfiguration"
|
||||||
|
:histogramVisible="histogramVisible" @setToolsPassive="setToolsPassive"
|
||||||
@resetQuestion="resetQuestion" />
|
@resetQuestion="resetQuestion" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
<el-tab-pane :label="$t('trials:reading:dicom3D:tabs:ecrf')" name="ecrf">
|
<el-tab-pane :label="$t('trials:reading:dicom3D:tabs:ecrf')" name="ecrf">
|
||||||
|
|
@ -486,6 +511,14 @@
|
||||||
<SegmentForm ref="SegmentForm" v-if="segmentVisible" :visible.sync="segmentVisible" :visitInfo="segmentVisitInfo"
|
<SegmentForm ref="SegmentForm" v-if="segmentVisible" :visible.sync="segmentVisible" :visitInfo="segmentVisitInfo"
|
||||||
@handleSegmentSave="handleSegmentSave" />
|
@handleSegmentSave="handleSegmentSave" />
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
<!--直方图-->
|
||||||
|
<histogram ref="histogram" v-if="readingTool === 3" :visible.sync="histogramVisible" :activeTool.sync="activeTool"
|
||||||
|
:viewportKey="viewportKey" :rendering-engine-id="renderingEngineId" :activeViewportIndex="activeViewportIndex" />
|
||||||
|
<!--分割可视化窗口-->
|
||||||
|
<!-- <SurfaceViewport ref="surfaceViewport" viewportId="surfaceViewport" v-if="readingTool === 3"
|
||||||
|
:visible.sync="surfaceVisible" :renderingEngineId="renderingEngineId" :visitInfo="taskInfo" />
|
||||||
|
<ContourViewport ref="contourViewport" viewportId="contourViewport" v-if="readingTool === 3"
|
||||||
|
:renderingEngineId="renderingEngineId" :visitInfo="taskInfo" /> -->
|
||||||
<upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId"
|
<upload-dicom-and-nonedicom v-if="uploadImageVisible" :subject-id="uploadSubjectId"
|
||||||
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible"
|
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :visible.sync="uploadImageVisible"
|
||||||
:visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
|
:visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
|
||||||
|
|
@ -504,6 +537,7 @@ import {
|
||||||
RenderingEngine,
|
RenderingEngine,
|
||||||
Enums,
|
Enums,
|
||||||
// imageLoader,
|
// imageLoader,
|
||||||
|
// CONSTANTS,
|
||||||
metaData,
|
metaData,
|
||||||
volumeLoader,
|
volumeLoader,
|
||||||
getRenderingEngine,
|
getRenderingEngine,
|
||||||
|
|
@ -524,6 +558,9 @@ import PetCtViewport from './PetCtViewport'
|
||||||
import MPRViewport from './MPRViewport'
|
import MPRViewport from './MPRViewport'
|
||||||
import VolumeViewport from './VolumeViewport'
|
import VolumeViewport from './VolumeViewport'
|
||||||
import Segmentations from './Segmentations'
|
import Segmentations from './Segmentations'
|
||||||
|
import histogram from "./histogram"
|
||||||
|
// import SurfaceViewport from "./SurfaceViewport"
|
||||||
|
// import ContourViewport from "./ContourViewport"
|
||||||
import mRecisit from './mRecist/QuestionList'
|
import mRecisit from './mRecist/QuestionList'
|
||||||
import recisit from './Recist/QuestionList'
|
import recisit from './Recist/QuestionList'
|
||||||
import customizeQuestionList from './customize/QuestionList'
|
import customizeQuestionList from './customize/QuestionList'
|
||||||
|
|
@ -554,6 +591,9 @@ const {
|
||||||
ToolGroupManager,
|
ToolGroupManager,
|
||||||
Enums: csToolsEnums,
|
Enums: csToolsEnums,
|
||||||
StackScrollTool,
|
StackScrollTool,
|
||||||
|
TrackballRotateTool,
|
||||||
|
PlanarFreehandContourSegmentationTool,
|
||||||
|
SplineContourSegmentationTool,
|
||||||
// ScaleOverlayTool,
|
// ScaleOverlayTool,
|
||||||
PanTool,
|
PanTool,
|
||||||
ZoomTool,
|
ZoomTool,
|
||||||
|
|
@ -615,6 +655,9 @@ export default {
|
||||||
MPRViewport,
|
MPRViewport,
|
||||||
VolumeViewport,
|
VolumeViewport,
|
||||||
Segmentations,
|
Segmentations,
|
||||||
|
histogram,
|
||||||
|
// SurfaceViewport,
|
||||||
|
// ContourViewport,
|
||||||
mRecisit,
|
mRecisit,
|
||||||
recisit,
|
recisit,
|
||||||
customizeQuestionList,
|
customizeQuestionList,
|
||||||
|
|
@ -648,7 +691,7 @@ export default {
|
||||||
activeTaskIndex: -1,
|
activeTaskIndex: -1,
|
||||||
activeStudyIndex: -1,
|
activeStudyIndex: -1,
|
||||||
activeSeriesIndex: -1,
|
activeSeriesIndex: -1,
|
||||||
currentVisitInfo: null,
|
currentVisitInfo: {},
|
||||||
layout: 1,
|
layout: 1,
|
||||||
cellsMax: 4,
|
cellsMax: 4,
|
||||||
rows: 1,
|
rows: 1,
|
||||||
|
|
@ -729,6 +772,7 @@ export default {
|
||||||
|
|
||||||
isMPR: false,
|
isMPR: false,
|
||||||
volumeToolGroupId: "share-viewport-volume",
|
volumeToolGroupId: "share-viewport-volume",
|
||||||
|
fusionToolGroupId: "share-viewport-fusion",
|
||||||
MPRInfo: {
|
MPRInfo: {
|
||||||
AXIAL: {
|
AXIAL: {
|
||||||
imageNum: 0
|
imageNum: 0
|
||||||
|
|
@ -758,12 +802,28 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
SegmentConfig: {
|
||||||
|
renderOutline: true,
|
||||||
|
renderFill: true,
|
||||||
|
fillAlpha: 0.5,
|
||||||
|
outlineWidth: 1,
|
||||||
|
InactiveSegmentations: {
|
||||||
|
show: true,
|
||||||
|
fillAlpha: 0.3,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
segId: null,
|
||||||
|
segIndex: null,
|
||||||
|
curSegSeries: {},
|
||||||
fusionOverlayModality: null,
|
fusionOverlayModality: null,
|
||||||
lastUpper: null,
|
lastUpper: null,
|
||||||
hasFusionUpperInitialized: false,
|
hasFusionUpperInitialized: false,
|
||||||
timer: null,
|
timer: {},
|
||||||
FullTimerOut: null,
|
FullTimerOut: null,
|
||||||
isDelay: false
|
isDelay: false,
|
||||||
|
|
||||||
|
histogramVisible: false,
|
||||||
|
// surfaceVisible: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -856,7 +916,38 @@ export default {
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
// histogramVisible: {
|
||||||
|
// handler() {
|
||||||
|
// if (this.readingTool !== 3) return false
|
||||||
|
// this.setToolsPassive()
|
||||||
|
// let viewportIds = ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3', this.volumeToolGroupId]
|
||||||
|
// // if (this.isMPR) {
|
||||||
|
// // viewportIds = [this.volumeToolGroupId]
|
||||||
|
// // }
|
||||||
|
// viewportIds.forEach(id => {
|
||||||
|
// const toolGroup = ToolGroupManager.getToolGroup(id)
|
||||||
|
// if (this.histogramVisible) {
|
||||||
|
// toolGroup.setToolEnabled(StackScrollTool.toolName)
|
||||||
|
// } else {
|
||||||
|
// toolGroup.setToolActive(StackScrollTool.toolName, {
|
||||||
|
// bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||||
|
// })
|
||||||
|
// let annotations = annotation.state.getAllAnnotations().filter(item => item.metadata.toolName.includes('histogram_'));
|
||||||
|
// annotations.forEach(item => {
|
||||||
|
// annotation.state.removeAnnotation(item.annotationUID)
|
||||||
|
// })
|
||||||
|
// for (let i = 0; i < this.cells.length; i++) {
|
||||||
|
// const viewportId = `${this.viewportKey}-${i}`
|
||||||
|
// let renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
// const viewport = renderingEngine.getViewport(viewportId)
|
||||||
|
// viewport.render()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// },
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo'))
|
this.taskInfo = JSON.parse(sessionStorage.getItem('taskInfo'))
|
||||||
|
|
@ -904,6 +995,36 @@ export default {
|
||||||
this.getSystemInfoReading();
|
this.getSystemInfoReading();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
resetHistogram() {
|
||||||
|
if (!this.histogramVisible) return false
|
||||||
|
if (this.timer['histogram']) {
|
||||||
|
clearTimeout(this.timer['histogram'])
|
||||||
|
this.timer['histogram'] = null
|
||||||
|
}
|
||||||
|
this.timer['histogram'] = setTimeout(() => {
|
||||||
|
if (this.$refs.histogram && this.histogramVisible) {
|
||||||
|
this.$refs.histogram.init()
|
||||||
|
}
|
||||||
|
clearTimeout(this.timer['histogram'])
|
||||||
|
this.timer['histogram'] = null
|
||||||
|
}, 500)
|
||||||
|
|
||||||
|
},
|
||||||
|
showSurface(obj) {
|
||||||
|
// this.surfaceVisible = true
|
||||||
|
// this.$refs.contourViewport.setSeriesInfo(obj)
|
||||||
|
// this.$refs.surfaceViewport.setSeriesInfo(obj)
|
||||||
|
},
|
||||||
|
async openHistogram() {
|
||||||
|
this.histogramVisible = true
|
||||||
|
this.setToolsPassive()
|
||||||
|
this.$refs.histogram.init()
|
||||||
|
|
||||||
|
},
|
||||||
|
handleSizeChange(e, viewportId) {
|
||||||
|
let index = this.$refs[viewportId][0].series.SliceIndex
|
||||||
|
this.resetRenderingEngine(viewportId, index)
|
||||||
|
},
|
||||||
resetQuestion() {
|
resetQuestion() {
|
||||||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].getQuestions(false)
|
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].getQuestions(false)
|
||||||
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].initSegmentBinding()
|
this.$refs[`ecrf_${this.lastViewportTaskId}`][0].initSegmentBinding()
|
||||||
|
|
@ -1240,6 +1361,27 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
// let element5 = this.$refs.surfaceViewport.$el
|
||||||
|
// let element6 = this.$refs.contourViewport.$el
|
||||||
|
// viewportInputArray.push({
|
||||||
|
// viewportId: 'surfaceViewport',
|
||||||
|
// type: ViewportType.VOLUME_3D,
|
||||||
|
// element: element5,
|
||||||
|
// defaultOptions: {
|
||||||
|
// orientation: Enums.OrientationAxis.CORONAL,
|
||||||
|
// background: [1, 1, 1]
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// viewportInputArray.push({
|
||||||
|
// viewportId: 'contourViewport',
|
||||||
|
// type: ViewportType.ORTHOGRAPHIC,
|
||||||
|
// element: element6,
|
||||||
|
// defaultOptions: {
|
||||||
|
// orientation: Enums.OrientationAxis.AXIAL
|
||||||
|
// }
|
||||||
|
// })
|
||||||
|
// viewportIds.push('surfaceViewport')
|
||||||
|
// viewportIds.push('contourViewport')
|
||||||
}
|
}
|
||||||
if ((this.criterionType === 0 && this.readingTool === 0) || this.readingTool === 3) {
|
if ((this.criterionType === 0 && this.readingTool === 0) || this.readingTool === 3) {
|
||||||
const volumeElement1 = this.$refs['viewport-MPR-0'][0].$el
|
const volumeElement1 = this.$refs['viewport-MPR-0'][0].$el
|
||||||
|
|
@ -1279,6 +1421,7 @@ export default {
|
||||||
const fusionElement2 = this.$refs['viewport-fusion-1'][0].$el
|
const fusionElement2 = this.$refs['viewport-fusion-1'][0].$el
|
||||||
const fusionElement3 = this.$refs['viewport-fusion-2'][0].$el
|
const fusionElement3 = this.$refs['viewport-fusion-2'][0].$el
|
||||||
const fusionElement4 = this.$refs['viewport-fusion-3'][0].$el
|
const fusionElement4 = this.$refs['viewport-fusion-3'][0].$el
|
||||||
|
const fusionHiddenSag = this.$refs['viewport-fusion-hidden-sag']
|
||||||
const arr = [
|
const arr = [
|
||||||
{
|
{
|
||||||
viewportId: 'viewport-fusion-0',
|
viewportId: 'viewport-fusion-0',
|
||||||
|
|
@ -1313,13 +1456,23 @@ export default {
|
||||||
orientation: Enums.OrientationAxis.CORONAL,
|
orientation: Enums.OrientationAxis.CORONAL,
|
||||||
background: [1, 1, 1]
|
background: [1, 1, 1]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
viewportId: 'viewport-fusion-hidden-sag',
|
||||||
|
type: ViewportType.ORTHOGRAPHIC,
|
||||||
|
element: fusionHiddenSag,
|
||||||
|
defaultOptions: {
|
||||||
|
orientation: Enums.OrientationAxis.SAGITTAL,
|
||||||
|
background: [1, 1, 1]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
viewportInputArray = [...viewportInputArray, ...arr]
|
viewportInputArray = [...viewportInputArray, ...arr]
|
||||||
viewportIds = viewportIds.concat(fusionViewportIds)
|
viewportIds = viewportIds.concat(fusionViewportIds, ['viewport-fusion-hidden-sag'])
|
||||||
}
|
}
|
||||||
renderingEngine.setViewports(viewportInputArray)
|
renderingEngine.setViewports(viewportInputArray)
|
||||||
this.addAnnotationListeners()
|
this.addAnnotationListeners()
|
||||||
|
// cornerstoneTools.addTool(TrackballRotateTool)
|
||||||
cornerstoneTools.addTool(StackScrollTool)
|
cornerstoneTools.addTool(StackScrollTool)
|
||||||
cornerstoneTools.addTool(PanTool)
|
cornerstoneTools.addTool(PanTool)
|
||||||
cornerstoneTools.addTool(ZoomTool)
|
cornerstoneTools.addTool(ZoomTool)
|
||||||
|
|
@ -1344,24 +1497,63 @@ export default {
|
||||||
cornerstoneTools.addTool(LabelMapEditWithContourTool)
|
cornerstoneTools.addTool(LabelMapEditWithContourTool)
|
||||||
cornerstoneTools.addTool(BrushTool)
|
cornerstoneTools.addTool(BrushTool)
|
||||||
cornerstoneTools.addTool(SegmentBidirectionalTool)
|
cornerstoneTools.addTool(SegmentBidirectionalTool)
|
||||||
|
// cornerstoneTools.addTool(PlanarFreehandContourSegmentationTool);
|
||||||
|
// cornerstoneTools.addTool(SplineContourSegmentationTool);
|
||||||
viewportIds.forEach((viewportId, i) => {
|
viewportIds.forEach((viewportId, i) => {
|
||||||
// const toolGroupId = `viewport-${i}`
|
// const toolGroupId = `viewport-${i}`
|
||||||
let toolGroupId = viewportId
|
let toolGroupId = viewportId
|
||||||
if (volumeViewportIds.includes(viewportId)) {
|
if (volumeViewportIds.includes(viewportId)) {
|
||||||
toolGroupId = this.volumeToolGroupId
|
toolGroupId = this.volumeToolGroupId
|
||||||
|
} else if (viewportId.startsWith('viewport-fusion-')) {
|
||||||
|
toolGroupId = this.fusionToolGroupId
|
||||||
}
|
}
|
||||||
|
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) ? ToolGroupManager.getToolGroup(toolGroupId) : ToolGroupManager.createToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) ? ToolGroupManager.getToolGroup(toolGroupId) : ToolGroupManager.createToolGroup(toolGroupId)
|
||||||
toolGroup.addViewport(viewportId, renderingEngineId)
|
toolGroup.addViewport(viewportId, renderingEngineId)
|
||||||
|
if (toolGroupId.includes('surface')) {
|
||||||
|
// toolGroup.addTool(TrackballRotateTool.toolName, {
|
||||||
|
// rotateSampleDistanceFactor: 0,
|
||||||
|
// });
|
||||||
|
// toolGroup.setToolActive(TrackballRotateTool.toolName, {
|
||||||
|
// bindings: [
|
||||||
|
// {
|
||||||
|
// mouseButton: MouseBindings.Primary,
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
} else if (toolGroupId.includes('contour')) {
|
||||||
|
// toolGroup.addTool(PlanarFreehandContourSegmentationTool.toolName);
|
||||||
|
// toolGroup.addTool(SplineContourSegmentationTool.toolName);
|
||||||
|
// toolGroup.setToolActive(PlanarFreehandContourSegmentationTool.toolName, {
|
||||||
|
// bindings: [
|
||||||
|
// {
|
||||||
|
// mouseButton: MouseBindings.Primary, // Middle Click
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// });
|
||||||
|
} else {
|
||||||
toolGroup.addTool(StackScrollTool.toolName, {
|
toolGroup.addTool(StackScrollTool.toolName, {
|
||||||
loop: true, // 启用循环滚动
|
loop: true, // 启用循环滚动
|
||||||
})
|
})
|
||||||
|
|
||||||
toolGroup.addTool(ScaleOverlayTool.toolName)
|
toolGroup.addTool(ScaleOverlayTool.toolName)
|
||||||
|
|
||||||
toolGroup.addTool(PanTool.toolName)
|
toolGroup.addTool(PanTool.toolName)
|
||||||
toolGroup.addTool(ZoomTool.toolName)
|
toolGroup.addTool(ZoomTool.toolName)
|
||||||
toolGroup.addTool(BrushTool.toolName)
|
toolGroup.addTool(BrushTool.toolName)
|
||||||
if (this.readingTool === 3 || toolGroupId === this.volumeToolGroupId) {
|
if (this.readingTool === 3 || toolGroupId === this.volumeToolGroupId) {
|
||||||
|
toolGroup.addToolInstance(
|
||||||
|
'histogram_RectangleROI',
|
||||||
|
RectangleROITool.toolName,
|
||||||
|
);
|
||||||
|
toolGroup.addToolInstance(
|
||||||
|
'histogram_CircleROI',
|
||||||
|
CircleROITool.toolName,
|
||||||
|
);
|
||||||
|
toolGroup.addToolInstance(
|
||||||
|
'histogram_PlanarFreehandROI',
|
||||||
|
PlanarFreehandROITool.toolName,
|
||||||
|
);
|
||||||
toolGroup.addToolInstance(
|
toolGroup.addToolInstance(
|
||||||
'CircularBrush',
|
'CircularBrush',
|
||||||
BrushTool.toolName,
|
BrushTool.toolName,
|
||||||
|
|
@ -1409,6 +1601,11 @@ export default {
|
||||||
toolGroup.addTool(CrosshairsTool.toolName, {
|
toolGroup.addTool(CrosshairsTool.toolName, {
|
||||||
getReferenceLineColor: this.setCrosshairsToolLineColor
|
getReferenceLineColor: this.setCrosshairsToolLineColor
|
||||||
});
|
});
|
||||||
|
} else if (toolGroupId === this.fusionToolGroupId) {
|
||||||
|
toolGroup.addTool(CrosshairsTool.toolName, {
|
||||||
|
getReferenceLineColor: this.setCrosshairsToolLineColor,
|
||||||
|
getReferenceLineSlabThicknessControlsOn: (otherViewportId) => otherViewportId !== 'viewport-fusion-3'
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
toolGroup.addTool(WindowLevelTool.toolName)
|
toolGroup.addTool(WindowLevelTool.toolName)
|
||||||
}
|
}
|
||||||
|
|
@ -1450,26 +1647,20 @@ export default {
|
||||||
toolGroup.addTool(EllipticalROITool.toolName, {
|
toolGroup.addTool(EllipticalROITool.toolName, {
|
||||||
getTextLines: this.getEllipticalROIToolTextLines
|
getTextLines: this.getEllipticalROIToolTextLines
|
||||||
})
|
})
|
||||||
toolGroup.addTool(FixedRadiusCircleROITool.toolName), {
|
toolGroup.addTool(FixedRadiusCircleROITool.toolName, {
|
||||||
|
radius: Number.isFinite(this.taskInfo.CircleRadius) ? this.taskInfo.CircleRadius : 6,
|
||||||
getTextLines: this.getCircleROIToolTextLines
|
getTextLines: this.getCircleROIToolTextLines
|
||||||
}
|
})
|
||||||
toolGroup.addTool(AngleTool.toolName, {
|
toolGroup.addTool(AngleTool.toolName, {
|
||||||
getTextLines: this.getAngleToolTextLines
|
getTextLines: this.getAngleToolTextLines
|
||||||
})
|
})
|
||||||
toolGroup.addTool(CobbAngleTool.toolName, {
|
toolGroup.addTool(CobbAngleTool.toolName, {
|
||||||
getTextLines: this.getCobbAngleToolTextLines
|
getTextLines: this.getCobbAngleToolTextLines
|
||||||
})
|
})
|
||||||
if (toolGroupId === 'viewport-fusion-3') {
|
if (viewportId === 'viewport-fusion-3') {
|
||||||
toolGroup.addTool(VolumeRotateTool.toolName)
|
toolGroup.addTool(VolumeRotateTool.toolName)
|
||||||
toolGroup.setToolActive(VolumeRotateTool.toolName, {
|
|
||||||
bindings: [
|
|
||||||
{
|
|
||||||
mouseButton: MouseBindings.Wheel // mouse wheel
|
|
||||||
}
|
|
||||||
]
|
|
||||||
})
|
|
||||||
toolGroup.addTool(MIPJumpToClickTool.toolName, {
|
toolGroup.addTool(MIPJumpToClickTool.toolName, {
|
||||||
targetViewportIds: fusionViewportIds.filter((id) => id !== toolGroupId)
|
targetViewportIds: fusionViewportIds.filter((id) => id !== viewportId)
|
||||||
})
|
})
|
||||||
|
|
||||||
// Set the initial state of the tools, here we set one tool active on left click.
|
// Set the initial state of the tools, here we set one tool active on left click.
|
||||||
|
|
@ -1482,6 +1673,7 @@ export default {
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
toolGroup.setToolConfiguration(
|
toolGroup.setToolConfiguration(
|
||||||
ScaleOverlayTool.toolName,
|
ScaleOverlayTool.toolName,
|
||||||
{
|
{
|
||||||
|
|
@ -1501,7 +1693,6 @@ export default {
|
||||||
toolGroup.setToolPassive(WindowLevelTool.toolName)
|
toolGroup.setToolPassive(WindowLevelTool.toolName)
|
||||||
toolGroup.setToolPassive(WindowLevelRegionTool.toolName)
|
toolGroup.setToolPassive(WindowLevelRegionTool.toolName)
|
||||||
toolGroup.setToolPassive(PlanarRotateTool.toolName)
|
toolGroup.setToolPassive(PlanarRotateTool.toolName)
|
||||||
|
|
||||||
if (this.readingTaskState < 2) {
|
if (this.readingTaskState < 2) {
|
||||||
toolGroup.setToolPassive(ArrowAnnotateTool.toolName)
|
toolGroup.setToolPassive(ArrowAnnotateTool.toolName)
|
||||||
toolGroup.setToolPassive(RectangleROITool.toolName)
|
toolGroup.setToolPassive(RectangleROITool.toolName)
|
||||||
|
|
@ -1528,9 +1719,14 @@ export default {
|
||||||
toolGroup.setToolEnabled(FixedRadiusCircleROITool.toolName)
|
toolGroup.setToolEnabled(FixedRadiusCircleROITool.toolName)
|
||||||
toolGroup.setToolEnabled(AngleTool.toolName)
|
toolGroup.setToolEnabled(AngleTool.toolName)
|
||||||
toolGroup.setToolEnabled(CobbAngleTool.toolName)
|
toolGroup.setToolEnabled(CobbAngleTool.toolName)
|
||||||
if (this.readingTool === 3) toolGroup.setToolEnabled(LabelMapEditWithContourTool.toolName)
|
if (this.readingTool === 3) {
|
||||||
|
toolGroup.setToolEnabled(LabelMapEditWithContourTool.toolName)
|
||||||
|
toolGroup.setToolEnabled(SegmentBidirectionalTool.toolName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
toolGroup.setToolPassive(EraserTool.toolName)
|
toolGroup.setToolPassive(EraserTool.toolName)
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
eventTarget.addEventListener('cornerstoneimageloadprogress', this.imageLoadProgress)
|
eventTarget.addEventListener('cornerstoneimageloadprogress', this.imageLoadProgress)
|
||||||
// console.log(Events, toolsEvents)
|
// console.log(Events, toolsEvents)
|
||||||
|
|
@ -1570,6 +1766,10 @@ export default {
|
||||||
setNetWorkSpeedSizeAll(percentComplete, detail.total, imageId)
|
setNetWorkSpeedSizeAll(percentComplete, detail.total, imageId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.readingTool === 3) {
|
||||||
|
getNetWorkSpeed()
|
||||||
|
setNetWorkSpeedSizeAll(percentComplete, detail.total, imageId)
|
||||||
|
}
|
||||||
if (percentComplete === 100) {
|
if (percentComplete === 100) {
|
||||||
workSpeedclose()
|
workSpeedclose()
|
||||||
}
|
}
|
||||||
|
|
@ -1674,9 +1874,10 @@ export default {
|
||||||
|
|
||||||
annotationCompletedListener(e) {
|
annotationCompletedListener(e) {
|
||||||
console.log('Completed')
|
console.log('Completed')
|
||||||
if (this.readingTaskState === 2) return
|
|
||||||
const { annotation } = e.detail
|
const { annotation } = e.detail
|
||||||
if (!annotation) return
|
if (!annotation) return
|
||||||
|
if (annotation.metadata.toolName.includes('histogram_')) return this.$refs.histogram.initToolValue(annotation)
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
|
|
@ -1699,10 +1900,11 @@ export default {
|
||||||
},
|
},
|
||||||
annotationModifiedListener(e) {
|
annotationModifiedListener(e) {
|
||||||
console.log('Modified')
|
console.log('Modified')
|
||||||
if (this.readingTaskState === 2) return
|
|
||||||
const { annotation } = e.detail
|
const { annotation } = e.detail
|
||||||
if (!annotation.highlighted) return
|
|
||||||
if (!annotation) return
|
if (!annotation) return
|
||||||
|
if (annotation.metadata.toolName.includes('histogram_')) return this.$refs.histogram.initToolValue(annotation)
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
|
if (!annotation.highlighted) return
|
||||||
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
|
|
@ -1742,9 +1944,10 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async customAnnotationCompletedListener(e) {
|
async customAnnotationCompletedListener(e) {
|
||||||
if (this.readingTaskState === 2) return
|
|
||||||
const { annotation } = e.detail
|
const { annotation } = e.detail
|
||||||
if (!annotation) return
|
if (!annotation) return
|
||||||
|
if (annotation.metadata.toolName.includes('histogram_')) return this.$refs.histogram.initToolValue(annotation)
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
||||||
if (i === -1) {
|
if (i === -1) {
|
||||||
if (annotation.metadata.toolName !== LabelMapEditWithContourTool.toolName) this.setToolsPassive()
|
if (annotation.metadata.toolName !== LabelMapEditWithContourTool.toolName) this.setToolsPassive()
|
||||||
|
|
@ -1829,10 +2032,11 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
customAnnotationModifiedListener(e) {
|
customAnnotationModifiedListener(e) {
|
||||||
if (this.readingTaskState === 2) return
|
|
||||||
const { annotation } = e.detail
|
const { annotation } = e.detail
|
||||||
if (!annotation.highlighted) return
|
|
||||||
if (!annotation) return
|
if (!annotation) return
|
||||||
|
if (annotation.metadata.toolName.includes('histogram_')) return this.$refs.histogram.initToolValue(annotation)
|
||||||
|
if (this.readingTaskState === 2) return
|
||||||
|
if (!annotation.highlighted) return
|
||||||
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
||||||
if (i === -1) {
|
if (i === -1) {
|
||||||
if (annotation.metadata.toolName !== LabelMapEditWithContourTool.toolName) this.setToolsPassive()
|
if (annotation.metadata.toolName !== LabelMapEditWithContourTool.toolName) this.setToolsPassive()
|
||||||
|
|
@ -1864,8 +2068,14 @@ export default {
|
||||||
const errorMsg = { message: 'annotation Not allowed to operate' }
|
const errorMsg = { message: 'annotation Not allowed to operate' }
|
||||||
throw errorMsg
|
throw errorMsg
|
||||||
}
|
}
|
||||||
|
if (this.activeTool !== 'Eraser') return false
|
||||||
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
const i = this.tools.findIndex(i => i.toolName === annotation.metadata.toolName)
|
||||||
if (i === -1) {
|
if (i === -1) {
|
||||||
|
if (annotation.metadata.toolName === SegmentBidirectionalTool.toolName) {
|
||||||
|
this.setToolsPassive()
|
||||||
|
const errorMsg = { message: 'SegmentBidirectionalTool Not remove' }
|
||||||
|
throw errorMsg
|
||||||
|
}
|
||||||
// 临时标记
|
// 临时标记
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -2315,21 +2525,61 @@ export default {
|
||||||
const factor = 10 ** precision
|
const factor = 10 ** precision
|
||||||
return (Math.round(num * factor + 0.0000001) / factor).toFixed(precision)
|
return (Math.round(num * factor + 0.0000001) / factor).toFixed(precision)
|
||||||
},
|
},
|
||||||
|
getActiveToolGroupId() {
|
||||||
|
if (this.isMPR) return this.volumeToolGroupId
|
||||||
|
if (this.isFusion) return this.fusionToolGroupId
|
||||||
|
return `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
|
},
|
||||||
|
getCurrentToolGroupIds() {
|
||||||
|
if (this.isMPR) return [this.volumeToolGroupId]
|
||||||
|
if (this.isFusion) return [this.fusionToolGroupId]
|
||||||
|
return [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`]
|
||||||
|
},
|
||||||
|
setFusionMipJumpEnabled(enabled) {
|
||||||
|
if (!this.isFusion) return
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId)
|
||||||
|
if (!toolGroup || !toolGroup.hasTool(MIPJumpToClickTool.toolName)) return
|
||||||
|
if (enabled) {
|
||||||
|
toolGroup.setToolActive(MIPJumpToClickTool.toolName, {
|
||||||
|
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
toolGroup.setToolDisabled(MIPJumpToClickTool.toolName)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setFusionMipRotateEnabled(enabled) {
|
||||||
|
if (!this.isFusion) return
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId)
|
||||||
|
if (!toolGroup || !toolGroup.hasTool(VolumeRotateTool.toolName)) return
|
||||||
|
if (enabled) {
|
||||||
|
toolGroup.setToolActive(VolumeRotateTool.toolName, {
|
||||||
|
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
toolGroup.setToolDisabled(VolumeRotateTool.toolName)
|
||||||
|
}
|
||||||
|
},
|
||||||
// 激活工具
|
// 激活工具
|
||||||
setToolActive(toolName) {
|
setToolActive(toolName) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
if (this.histogramVisible) return false
|
||||||
|
const toolGroupId = this.getActiveToolGroupId()
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
if (this.activeTool === toolName) {
|
if (this.activeTool === toolName) {
|
||||||
if (toolName === CrosshairsTool.toolName) {
|
if (toolName === CrosshairsTool.toolName) {
|
||||||
toolGroup.setToolDisabled(this.activeTool)
|
toolGroup.setToolDisabled(this.activeTool)
|
||||||
|
this.setFusionMipJumpEnabled(true)
|
||||||
|
this.setFusionMipRotateEnabled(true)
|
||||||
} else {
|
} else {
|
||||||
toolGroup.setToolPassive(this.activeTool)
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
}
|
}
|
||||||
this.activeTool = ''
|
this.activeTool = ''
|
||||||
} else {
|
} else {
|
||||||
if (this.activeTool) {
|
if (this.activeTool) {
|
||||||
if (toolName === CrosshairsTool.toolName) {
|
if (this.activeTool === CrosshairsTool.toolName) {
|
||||||
toolGroup.setToolDisabled(this.activeTool)
|
toolGroup.setToolDisabled(this.activeTool)
|
||||||
|
this.setFusionMipJumpEnabled(true)
|
||||||
|
this.setFusionMipRotateEnabled(true)
|
||||||
} else {
|
} else {
|
||||||
toolGroup.setToolPassive(this.activeTool)
|
toolGroup.setToolPassive(this.activeTool)
|
||||||
}
|
}
|
||||||
|
|
@ -2337,18 +2587,67 @@ export default {
|
||||||
toolGroup.setToolActive(toolName, {
|
toolGroup.setToolActive(toolName, {
|
||||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||||
})
|
})
|
||||||
|
if (toolName === CrosshairsTool.toolName) {
|
||||||
|
if (this.isFusion) {
|
||||||
|
const instance = toolGroup.getToolInstance?.(CrosshairsTool.toolName)
|
||||||
|
if (instance && !instance.__fusionSameForPatched) {
|
||||||
|
instance.__fusionSameForPatched = true
|
||||||
|
const original = instance._checkIfViewportsRenderingSameScene?.bind(instance)
|
||||||
|
instance._checkIfViewportsRenderingSameScene = (viewport, otherViewport) => {
|
||||||
|
try {
|
||||||
|
const a = viewport?.getFrameOfReferenceUID?.()
|
||||||
|
const b = otherViewport?.getFrameOfReferenceUID?.()
|
||||||
|
if (a && b && a === b) return true
|
||||||
|
} catch (e) { }
|
||||||
|
return original ? original(viewport, otherViewport) : true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.setFusionMipJumpEnabled(false)
|
||||||
|
this.setFusionMipRotateEnabled(false)
|
||||||
|
}
|
||||||
this.activeTool = toolName
|
this.activeTool = toolName
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
hoverFusionViewport(index) {
|
||||||
|
if (!this.isFusion) return
|
||||||
|
if (this.activeTool === CrosshairsTool.toolName) return
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(this.fusionToolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
|
|
||||||
|
const isMip = index === 3
|
||||||
|
this.setFusionMipJumpEnabled(isMip)
|
||||||
|
if (isMip) {
|
||||||
|
if (toolGroup.hasTool(StackScrollTool.toolName)) {
|
||||||
|
toolGroup.setToolDisabled(StackScrollTool.toolName)
|
||||||
|
}
|
||||||
|
if (toolGroup.hasTool(VolumeRotateTool.toolName)) {
|
||||||
|
toolGroup.setToolActive(VolumeRotateTool.toolName, {
|
||||||
|
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (toolGroup.hasTool(VolumeRotateTool.toolName)) {
|
||||||
|
toolGroup.setToolDisabled(VolumeRotateTool.toolName)
|
||||||
|
}
|
||||||
|
if (toolGroup.hasTool(StackScrollTool.toolName)) {
|
||||||
|
toolGroup.setToolActive(StackScrollTool.toolName, {
|
||||||
|
bindings: [{ mouseButton: MouseBindings.Wheel }]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
// 激活标注工具
|
// 激活标注工具
|
||||||
setAnnotateToolActive(toolName) {
|
setAnnotateToolActive(toolName) {
|
||||||
// if (this.readingTaskState === 2) return
|
// if (this.readingTaskState === 2) return
|
||||||
|
if (this.histogramVisible) return false
|
||||||
const toolObj = this.tools.find(i => i.toolName === toolName)
|
const toolObj = this.tools.find(i => i.toolName === toolName)
|
||||||
if (!toolObj || toolObj.isDisabled) return
|
if (!toolObj || toolObj.isDisabled) return
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.getActiveToolGroupId()
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
if (this.activeTool === toolName) {
|
if (this.activeTool === toolName) {
|
||||||
if (toolName === CrosshairsTool.toolName) {
|
if (toolName === CrosshairsTool.toolName) {
|
||||||
toolGroup.setToolDisabled(this.activeTool)
|
toolGroup.setToolDisabled(this.activeTool)
|
||||||
|
|
@ -2379,8 +2678,9 @@ export default {
|
||||||
if (this.activeTool === toolName) return
|
if (this.activeTool === toolName) return
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.getActiveToolGroupId()
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
if (this.activeTool) {
|
if (this.activeTool) {
|
||||||
if (this.activeTool === CrosshairsTool.toolName) {
|
if (this.activeTool === CrosshairsTool.toolName) {
|
||||||
toolGroup.setToolDisabled(this.activeTool)
|
toolGroup.setToolDisabled(this.activeTool)
|
||||||
|
|
@ -2399,8 +2699,9 @@ export default {
|
||||||
if (this.activeTool && this.toolNames.includes(this.activeTool)) {
|
if (this.activeTool && this.toolNames.includes(this.activeTool)) {
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.getActiveToolGroupId()
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
if (this.activeTool === CrosshairsTool.toolName) {
|
if (this.activeTool === CrosshairsTool.toolName) {
|
||||||
toolGroup.setToolDisabled(this.activeTool)
|
toolGroup.setToolDisabled(this.activeTool)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2412,11 +2713,13 @@ export default {
|
||||||
},
|
},
|
||||||
setMoreToolActive(toolName) {
|
setMoreToolActive(toolName) {
|
||||||
// if (this.readingTaskState === 2) return
|
// if (this.readingTaskState === 2) return
|
||||||
|
if (this.histogramVisible) return false
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.getActiveToolGroupId()
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
toolGroup.setToolActive(toolName, {
|
toolGroup.setToolActive(toolName, {
|
||||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||||
})
|
})
|
||||||
|
|
@ -2425,13 +2728,10 @@ export default {
|
||||||
},
|
},
|
||||||
setToolsPassive() {
|
setToolsPassive() {
|
||||||
if (!this.activeTool) return
|
if (!this.activeTool) return
|
||||||
let toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`]
|
const toolGroupIds = this.getCurrentToolGroupIds()
|
||||||
if (this.isMPR) {
|
|
||||||
// toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`]
|
|
||||||
toolGroupIds = [this.volumeToolGroupId]
|
|
||||||
}
|
|
||||||
toolGroupIds.forEach(toolGroupId => {
|
toolGroupIds.forEach(toolGroupId => {
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
if (this.activeTool === CrosshairsTool.toolName) {
|
if (this.activeTool === CrosshairsTool.toolName) {
|
||||||
toolGroup.setToolDisabled(this.activeTool)
|
toolGroup.setToolDisabled(this.activeTool)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -2442,13 +2742,10 @@ export default {
|
||||||
},
|
},
|
||||||
setToolEnabled() {
|
setToolEnabled() {
|
||||||
if (!this.activeTool) return
|
if (!this.activeTool) return
|
||||||
let toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`, `${this.viewportKey}-3`]
|
const toolGroupIds = this.getCurrentToolGroupIds()
|
||||||
if (this.isMPR) {
|
|
||||||
// toolGroupIds = [`${this.viewportKey}-0`, `${this.viewportKey}-1`, `${this.viewportKey}-2`]
|
|
||||||
toolGroupIds = [this.volumeToolGroupId]
|
|
||||||
}
|
|
||||||
toolGroupIds.forEach(toolGroupId => {
|
toolGroupIds.forEach(toolGroupId => {
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
toolGroup.setToolEnabled(this.activeTool)
|
toolGroup.setToolEnabled(this.activeTool)
|
||||||
})
|
})
|
||||||
this.activeTool = ''
|
this.activeTool = ''
|
||||||
|
|
@ -2531,20 +2828,28 @@ export default {
|
||||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
const viewport = renderingEngine.getViewport(viewportId)
|
const viewport = renderingEngine.getViewport(viewportId)
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resetOrientationMarkers()
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resetOrientationMarkers()
|
||||||
|
let index = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series.SliceIndex
|
||||||
|
if (this.readingTool !== 3) {
|
||||||
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
|
}
|
||||||
viewport.resetProperties()
|
viewport.resetProperties()
|
||||||
if (this.isMPR) {
|
if (this.isMPR) {
|
||||||
let volume = cache.getVolume(this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].volumeId)
|
let volume = cache.getVolume(this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].volumeId)
|
||||||
const voi = metaData.get('voiLutModule', volume._imageIds[Math.ceil((volume._imageIds.length - 1) / 2)])
|
const voi = metaData.get('voiLutModule', volume._imageIds[Math.ceil((volume._imageIds.length - 1) / 2)])
|
||||||
const lower = voi.windowCenter[0] - voi.windowWidth[0] / 2
|
const lower = voi.windowCenter[0] - voi.windowWidth[0] / 2
|
||||||
const upper = voi.windowCenter[0] + voi.windowWidth[0] / 2 - 1
|
const upper = voi.windowCenter[0] + voi.windowWidth[0] / 2 - 1
|
||||||
console.log(lower, upper)
|
|
||||||
viewport.setProperties({ voiRange: { upper: upper, lower: lower } })
|
viewport.setProperties({ voiRange: { upper: upper, lower: lower } })
|
||||||
}
|
}
|
||||||
|
if (this.readingTool === 3 && this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series.Modality === 'PT') {
|
||||||
|
viewport.setProperties({ voiRange: { upper: 5, lower: 0 } })
|
||||||
|
}
|
||||||
viewport.render()
|
viewport.render()
|
||||||
renderingEngine.render()
|
renderingEngine.render()
|
||||||
if (this.readingTool === 3) {
|
if (this.readingTool === 3) {
|
||||||
DicomEvent.$emit('isloaded', { isChange: false })
|
DicomEvent.$emit('isloaded', { isChange: false, viewportId })
|
||||||
|
}
|
||||||
|
if (this.readingTool === 3 || this.isMPR) {
|
||||||
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setFullScreen(index)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 更改视图布局
|
// 更改视图布局
|
||||||
|
|
@ -2553,6 +2858,7 @@ export default {
|
||||||
this.fullScreenIndex = null
|
this.fullScreenIndex = null
|
||||||
this.layout = v
|
this.layout = v
|
||||||
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
|
||||||
|
let index = series.SliceIndex
|
||||||
const seriesArr = []
|
const seriesArr = []
|
||||||
if (v === 1) {
|
if (v === 1) {
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
|
|
@ -2565,6 +2871,7 @@ export default {
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
this.cols = 2
|
this.cols = 2
|
||||||
this.activeViewportIndex = 1
|
this.activeViewportIndex = 1
|
||||||
|
series.curIndex = index
|
||||||
if (typeof series === 'object') {
|
if (typeof series === 'object') {
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
|
|
@ -2614,6 +2921,7 @@ export default {
|
||||||
} else if (v === 4) {
|
} else if (v === 4) {
|
||||||
this.rows = 2
|
this.rows = 2
|
||||||
this.cols = 2
|
this.cols = 2
|
||||||
|
series.curIndex = index
|
||||||
if (typeof series === 'object') {
|
if (typeof series === 'object') {
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
seriesArr.push(series)
|
seriesArr.push(series)
|
||||||
|
|
@ -2676,19 +2984,22 @@ export default {
|
||||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(`${this.viewportKey}-${this.activeViewportIndex}`)
|
const viewport = renderingEngine.getViewport(`${this.viewportKey}-${this.activeViewportIndex}`)
|
||||||
const { invert } = viewport.getProperties()
|
const { invert } = viewport.getProperties()
|
||||||
if (this.isFusion) {
|
if (this.isFusion || this.readingTool === 3) {
|
||||||
viewport.setProperties({ invert: !invert }, this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].volumeId)
|
viewport.setProperties({ invert: !invert }, this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].volumeId)
|
||||||
}
|
} else {
|
||||||
viewport.setProperties({ invert: !invert })
|
viewport.setProperties({ invert: !invert })
|
||||||
|
}
|
||||||
viewport.render()
|
viewport.render()
|
||||||
},
|
},
|
||||||
// 翻页
|
// 翻页
|
||||||
scrollPage(type) {
|
scrollPage(type) {
|
||||||
|
// if (this.histogramVisible) return false
|
||||||
this.clipPlaying = false
|
this.clipPlaying = false
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].scrollPage(type)
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].scrollPage(type)
|
||||||
},
|
},
|
||||||
// 播放
|
// 播放
|
||||||
toggleClipPlay(isPlay) {
|
toggleClipPlay(isPlay) {
|
||||||
|
// if (this.histogramVisible) return false
|
||||||
this.clipPlaying = !this.clipPlaying
|
this.clipPlaying = !this.clipPlaying
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].toggleClipPlay(isPlay, this.fps)
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].toggleClipPlay(isPlay, this.fps)
|
||||||
},
|
},
|
||||||
|
|
@ -2821,20 +3132,26 @@ export default {
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resize(forceFitToWindow)
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].resize(forceFitToWindow)
|
||||||
},
|
},
|
||||||
// 重置视口
|
// 重置视口
|
||||||
resetRenderingEngine() {
|
resetRenderingEngine(viewportId = null, i) {
|
||||||
if (this.timer) {
|
if (this.timer[viewportId]) {
|
||||||
clearInterval(this.timer)
|
clearInterval(this.timer[viewportId])
|
||||||
this.timer = null
|
this.timer[viewportId] = null
|
||||||
}
|
}
|
||||||
let index = null
|
|
||||||
this.timer = setTimeout(() => {
|
|
||||||
index = index || index === 0 ? index : this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series.SliceIndex
|
|
||||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(viewportId)
|
||||||
|
if (!viewport) return false
|
||||||
|
if (viewport.volumeIds.size <= 0) return false
|
||||||
|
let index = null
|
||||||
|
this.timer[viewportId] = setTimeout(() => {
|
||||||
|
index = i || i === 0 ? i : this.$refs[viewportId ? viewportId : `${this.viewportKey}-${this.activeViewportIndex}`][0].series.SliceIndex
|
||||||
renderingEngine.resize(true, false)
|
renderingEngine.resize(true, false)
|
||||||
renderingEngine.render()
|
renderingEngine.render()
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setFullScreen(index)
|
this.$refs[viewportId ? viewportId : `${this.viewportKey}-${this.activeViewportIndex}`][0].setFullScreen(index)
|
||||||
clearTimeout(this.timer)
|
clearTimeout(this.timer[viewportId])
|
||||||
this.timer = null
|
this.timer[viewportId] = null
|
||||||
|
if (this.readingTool === 3) {
|
||||||
|
DicomEvent.$emit('isloaded', { isChange: false, viewportId })
|
||||||
|
}
|
||||||
}, 100)
|
}, 100)
|
||||||
},
|
},
|
||||||
setDelay(time) {
|
setDelay(time) {
|
||||||
|
|
@ -2854,12 +3171,12 @@ export default {
|
||||||
if (this.readingTool === 3 || this.isMPR) {
|
if (this.readingTool === 3 || this.isMPR) {
|
||||||
// this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series)
|
// this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series)
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.resetRenderingEngine()
|
// this.resetRenderingEngine(`${this.viewportKey}-${index}`)
|
||||||
this.isDelay = true
|
this.isDelay = true
|
||||||
this.setDelay(2000)
|
this.setDelay(2000)
|
||||||
if (this.readingTool === 3) {
|
// if (this.readingTool === 3) {
|
||||||
DicomEvent.$emit('isloaded', { isChange: false })
|
// DicomEvent.$emit('isloaded', { isChange: false })
|
||||||
}
|
// }
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -2958,6 +3275,7 @@ export default {
|
||||||
const confirm = await this.$confirm(this.$t('trials:reading:confirm:changeStack'))
|
const confirm = await this.$confirm(this.$t('trials:reading:confirm:changeStack'))
|
||||||
if (!confirm) return false
|
if (!confirm) return false
|
||||||
}
|
}
|
||||||
|
if (this.histogramVisible) this.$refs.histogram.close()
|
||||||
this.isFusion = false
|
this.isFusion = false
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
this.rows = 1
|
this.rows = 1
|
||||||
|
|
@ -2966,8 +3284,10 @@ export default {
|
||||||
this.fullScreenIndex = null
|
this.fullScreenIndex = null
|
||||||
this.isMPR = false
|
this.isMPR = false
|
||||||
obj.isChange = false
|
obj.isChange = false
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
|
||||||
return this.$nextTick(() => {
|
return this.$nextTick(() => {
|
||||||
|
DicomEvent.$emit('activeSeries', obj)
|
||||||
|
DicomEvent.$emit('changeMPR')
|
||||||
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(obj)
|
||||||
const renderingEngine = getRenderingEngine(renderingEngineId)
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
renderingEngine.resize(true, false)
|
renderingEngine.resize(true, false)
|
||||||
renderingEngine.render()
|
renderingEngine.render()
|
||||||
|
|
@ -2977,6 +3297,7 @@ export default {
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
|
if (this.histogramVisible) this.$refs.histogram.close()
|
||||||
if (!obj.IsDicom) {
|
if (!obj.IsDicom) {
|
||||||
return this.previewNoneDicoms(obj)
|
return this.previewNoneDicoms(obj)
|
||||||
}
|
}
|
||||||
|
|
@ -3015,7 +3336,14 @@ export default {
|
||||||
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
|
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (this.readingTool === 3) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
DicomEvent.$emit('SegmentationLoading', `${this.viewportKey}-${this.activeViewportIndex}`)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (this.activeTool !== CrosshairsTool.toolName) {
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
getRelatedSeries(visitTaskInfo, baselineSeries) {
|
getRelatedSeries(visitTaskInfo, baselineSeries) {
|
||||||
let obj = {}
|
let obj = {}
|
||||||
|
|
@ -3139,13 +3467,15 @@ export default {
|
||||||
if (i === -1) return
|
if (i === -1) return
|
||||||
const studyList = this.visitTaskList[i].StudyList
|
const studyList = this.visitTaskList[i].StudyList
|
||||||
let series = null
|
let series = null
|
||||||
|
let curSeriesId = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series.Id
|
||||||
if (obj.segment) {
|
if (obj.segment) {
|
||||||
let study = studyList.find(item => item.StudyId === obj.segmentGroup.StudyId)
|
let study = studyList.find(item => item.StudyId === obj.segmentGroup.StudyId)
|
||||||
series = study.SeriesList.find(item => item.Id === obj.segmentGroup.SeriesId)
|
let Series = study.SeriesList.find(item => item.Id === obj.segmentGroup.SeriesId)
|
||||||
series.SliceIndex = 0
|
Series.SliceIndex = 0
|
||||||
series.segment = obj.segment
|
series = Object.assign(Series, { segment: obj.segment })
|
||||||
} else {
|
} else {
|
||||||
series = this.getMarkedSeries(studyList, obj.annotation, true)
|
series = this.getMarkedSeries(studyList, obj.annotation, true)
|
||||||
|
delete series.segment
|
||||||
}
|
}
|
||||||
|
|
||||||
if (series) {
|
if (series) {
|
||||||
|
|
@ -3188,7 +3518,7 @@ export default {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series, obj.segment ? false : true)
|
this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].setSeriesInfo(series, series.segment || curSeriesId !== series.Id ? false : true)
|
||||||
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
|
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -3380,8 +3710,9 @@ export default {
|
||||||
this.setToolsPassive()
|
this.setToolsPassive()
|
||||||
|
|
||||||
}
|
}
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.getActiveToolGroupId()
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
|
if (!toolGroup) return
|
||||||
toolGroup.setToolActive(toolName, {
|
toolGroup.setToolActive(toolName, {
|
||||||
bindings: [{ mouseButton: MouseBindings.Primary }]
|
bindings: [{ mouseButton: MouseBindings.Primary }]
|
||||||
})
|
})
|
||||||
|
|
@ -3656,6 +3987,8 @@ export default {
|
||||||
if (series.ImageIds.length <= 5) return this.$confirm(this.$t('trials:reading:confirm:smallNumberOfimage'), this.$t('system:menu:confirm:title:warning'), {
|
if (series.ImageIds.length <= 5) return this.$confirm(this.$t('trials:reading:confirm:smallNumberOfimage'), this.$t('system:menu:confirm:title:warning'), {
|
||||||
type: 'warning'
|
type: 'warning'
|
||||||
})
|
})
|
||||||
|
series.curIndex = series.SliceIndex
|
||||||
|
DicomEvent.$emit('changeMPR')
|
||||||
if (series.ImageIds.length > 500) {
|
if (series.ImageIds.length > 500) {
|
||||||
let res = await this.getSystemInfo()
|
let res = await this.getSystemInfo()
|
||||||
if (!res) return false
|
if (!res) return false
|
||||||
|
|
@ -3740,6 +4073,7 @@ export default {
|
||||||
this.$refs[`viewport-fusion-1`][0].setSeriesInfo(ptData, false, { colorMap: false })
|
this.$refs[`viewport-fusion-1`][0].setSeriesInfo(ptData, false, { colorMap: false })
|
||||||
this.$refs[`viewport-fusion-2`][0].setSeriesInfo(fusionData, false, { isFusion: true, colorMap: true })
|
this.$refs[`viewport-fusion-2`][0].setSeriesInfo(fusionData, false, { isFusion: true, colorMap: true })
|
||||||
this.$refs[`viewport-fusion-3`][0].setSeriesInfo(ptData, false, { isMip: true, colorMap: false })
|
this.$refs[`viewport-fusion-3`][0].setSeriesInfo(ptData, false, { isMip: true, colorMap: false })
|
||||||
|
await this.initFusionHiddenSagViewport(pt)
|
||||||
// this.resetAnnotation = false
|
// this.resetAnnotation = false
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs[`colorMap`].init()
|
this.$refs[`colorMap`].init()
|
||||||
|
|
@ -3770,6 +4104,18 @@ export default {
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
},
|
},
|
||||||
|
async initFusionHiddenSagViewport(pt) {
|
||||||
|
const ptVolumeId = pt?.SeriesInstanceUid
|
||||||
|
if (!ptVolumeId || !cache.getVolume(ptVolumeId)) return
|
||||||
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
const sagViewport = renderingEngine?.getViewport?.('viewport-fusion-hidden-sag')
|
||||||
|
if (!sagViewport) return
|
||||||
|
|
||||||
|
await sagViewport.setVolumes([{ volumeId: ptVolumeId }])
|
||||||
|
const midIndex = Math.max(0, Math.floor((pt.ImageIds?.length || 1) / 2))
|
||||||
|
await csUtils.jumpToSlice(sagViewport.element, { imageIndex: midIndex })
|
||||||
|
sagViewport.render()
|
||||||
|
},
|
||||||
async getVolume(serie, isFusion = false) {
|
async getVolume(serie, isFusion = false) {
|
||||||
return new Promise(async res => {
|
return new Promise(async res => {
|
||||||
let volumeId = `${isFusion ? 'fusion_' : ''}` + serie.SeriesInstanceUid;
|
let volumeId = `${isFusion ? 'fusion_' : ''}` + serie.SeriesInstanceUid;
|
||||||
|
|
@ -3954,8 +4300,14 @@ export default {
|
||||||
this.saveCustomAnnotationTimer = null
|
this.saveCustomAnnotationTimer = null
|
||||||
}
|
}
|
||||||
if (this.timer) {
|
if (this.timer) {
|
||||||
clearInterval(this.timer)
|
Object.keys(this.timer).forEach(key => {
|
||||||
this.timer = null
|
if (this.timer[key]) {
|
||||||
|
clearInterval(this.timer[key])
|
||||||
|
clearTimeout(this.timer[key])
|
||||||
|
this.timer[key] = null
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.timer = {}
|
||||||
}
|
}
|
||||||
if (this.FullTimerOut) {
|
if (this.FullTimerOut) {
|
||||||
clearTimeout(this.FullTimerOut)
|
clearTimeout(this.FullTimerOut)
|
||||||
|
|
@ -4255,6 +4607,22 @@ export default {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fusion-hidden-viewports {
|
||||||
|
position: absolute;
|
||||||
|
left: -100000px;
|
||||||
|
top: -100000px;
|
||||||
|
width: 512px;
|
||||||
|
height: 512px;
|
||||||
|
overflow: hidden;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.fusion-hidden-viewport {
|
||||||
|
width: 512px;
|
||||||
|
height: 512px;
|
||||||
|
}
|
||||||
|
|
||||||
.viewports-box {
|
.viewports-box {
|
||||||
display: grid;
|
display: grid;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
|
|
|
||||||
|
|
@ -2,21 +2,24 @@
|
||||||
<el-form ref="segmentForm" :model="form" label-width="120px" label-position="left" :rules="rules">
|
<el-form ref="segmentForm" :model="form" label-width="120px" label-position="left" :rules="rules">
|
||||||
<!-- 检查名称 -->
|
<!-- 检查名称 -->
|
||||||
<el-form-item :label="$t('segment:form:label:studyName')" prop="taskBlindName">
|
<el-form-item :label="$t('segment:form:label:studyName')" prop="taskBlindName">
|
||||||
<el-select v-model="form.studyId" clearable @change="(e) => handleChange(e, 'study')">
|
<el-select v-model="form.studyId" clearable @change="(e) => handleChange(e, 'study')"
|
||||||
|
@clear="(e) => handleClear(e, 'study')">
|
||||||
<el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode"
|
<el-option v-for="item in studyList" :key="item.StudyId" :label="item.StudyCode"
|
||||||
:value="item.StudyId" />
|
:value="item.StudyId" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 序列名称 -->
|
<!-- 序列名称 -->
|
||||||
<el-form-item :label="$t('segment:form:label:seriesName')" prop="taskBlindName">
|
<el-form-item :label="$t('segment:form:label:seriesName')" prop="taskBlindName">
|
||||||
<el-select v-model="form.seriesId" clearable @change="(e) => handleChange(e, 'series')">
|
<el-select v-model="form.seriesId" clearable @change="(e) => handleChange(e, 'series')"
|
||||||
|
@clear="(e) => handleClear(e, 'series')">
|
||||||
<el-option v-for="item in seriesList" :key="item.Id"
|
<el-option v-for="item in seriesList" :key="item.Id"
|
||||||
:label="`#${item.SeriesNumber}/${item.Modality}/${item.Description}`" :value="item.Id" />
|
:label="`#${item.SeriesNumber}/${item.Modality}/${item.Description}`" :value="item.Id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 分割组名称 -->
|
<!-- 分割组名称 -->
|
||||||
<el-form-item :label="$t('segment:form:label:segmentGroupName')" prop="segmentGroupId">
|
<el-form-item :label="$t('segment:form:label:segmentGroupName')" prop="segmentGroupId">
|
||||||
<el-select v-model="form.segmentGroupId" clearable @change="(e) => handleChange(e, 'segmentGroup')">
|
<el-select v-model="form.segmentGroupId" clearable @change="(e) => handleChange(e, 'segmentGroup')"
|
||||||
|
@clear="(e) => handleClear(e, 'segmentGroup')">
|
||||||
<el-option v-for="item in segmentGroupList" :key="item.Id" :label="item.SegmentationName"
|
<el-option v-for="item in segmentGroupList" :key="item.Id" :label="item.SegmentationName"
|
||||||
:value="item.Id" />
|
:value="item.Id" />
|
||||||
</el-select>
|
</el-select>
|
||||||
|
|
@ -106,11 +109,22 @@ export default {
|
||||||
})
|
})
|
||||||
this.studyList = studyList
|
this.studyList = studyList
|
||||||
if (this.visitInfo.operateStateEnum === 21) {
|
if (this.visitInfo.operateStateEnum === 21) {
|
||||||
|
let find = studyList.some(item => item.StudyId === this.series.StudyId)
|
||||||
|
if (find) {
|
||||||
this.form.studyId = this.series.StudyId
|
this.form.studyId = this.series.StudyId
|
||||||
this.handleChange(null, 'study')
|
this.handleChange(null, 'study')
|
||||||
|
if (find.SeriesArr && find.SeriesArr.length > 0) {
|
||||||
|
let findSeries = find.SeriesArr.some(item => item.Id === this.form.seriesId)
|
||||||
|
if (findSeries) {
|
||||||
this.form.seriesId = this.series.Id
|
this.form.seriesId = this.series.Id
|
||||||
this.handleChange(null, 'series')
|
this.handleChange(null, 'series')
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
if (this.visitInfo.operateStateEnum === 22) {
|
if (this.visitInfo.operateStateEnum === 22) {
|
||||||
let o = {}
|
let o = {}
|
||||||
if (this.isTableQuestion) {
|
if (this.isTableQuestion) {
|
||||||
|
|
@ -132,6 +146,7 @@ export default {
|
||||||
},
|
},
|
||||||
async handleChange(e, key) {
|
async handleChange(e, key) {
|
||||||
if (key === 'study') {
|
if (key === 'study') {
|
||||||
|
console.log(this.studyList, 'this.studyList')
|
||||||
this.seriesList = this.studyList.find(item => item.StudyId === this.form.studyId).SeriesArr
|
this.seriesList = this.studyList.find(item => item.StudyId === this.form.studyId).SeriesArr
|
||||||
}
|
}
|
||||||
if (key === 'series') {
|
if (key === 'series') {
|
||||||
|
|
@ -142,6 +157,20 @@ export default {
|
||||||
this.segmentList = list.filter(item => item.SegmentJson)
|
this.segmentList = list.filter(item => item.SegmentJson)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
handleClear(e, key) {
|
||||||
|
if (key === 'study') {
|
||||||
|
this.form.seriesId = null
|
||||||
|
this.form.segmentGroupId = null
|
||||||
|
this.form.segmentId = null
|
||||||
|
}
|
||||||
|
if (key === 'series') {
|
||||||
|
this.form.segmentGroupId = null
|
||||||
|
this.form.segmentId = null
|
||||||
|
}
|
||||||
|
if (key === 'segmentGroup') {
|
||||||
|
this.form.segmentId = null
|
||||||
|
}
|
||||||
|
},
|
||||||
handleCancel() {
|
handleCancel() {
|
||||||
this.$emit("update:visible", false)
|
this.$emit("update:visible", false)
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -8,25 +8,26 @@
|
||||||
<div class="tool-frame">
|
<div class="tool-frame">
|
||||||
<div :title="$t('trials:Segmentations:tools:contour')"
|
<div :title="$t('trials:Segmentations:tools:contour')"
|
||||||
:class="['tool-item', activeTool === 'LabelMapEditWithContour' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
:class="['tool-item', activeTool === 'LabelMapEditWithContour' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
@click.prevent="setToolActive('LabelMapEditWithContour')">
|
@click.prevent="setToolActive('LabelMapEditWithContour')">
|
||||||
<svg-icon icon-class="contour" class="svg-icon" />
|
<svg-icon icon-class="contour" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div :title="$t('trials:Segmentations:tools:thresholecircle')"
|
<div :title="$t('trials:Segmentations:tools:thresholecircle')"
|
||||||
:class="['tool-item', ThresholdTools.includes(activeTool) && segmentList.length > 0 ? 'tool-item-active' : '']"
|
:class="['tool-item', ThresholdTools.includes(activeTool) && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
@click.prevent="initThreshold">
|
@click.prevent="initThreshold">
|
||||||
<svg-icon icon-class="thresholecircle" class="svg-icon" />
|
<svg-icon icon-class="thresholecircle" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div :title="$t('trials:Segmentations:tools:circularbrush')"
|
<div :title="$t('trials:Segmentations:tools:circularbrush')"
|
||||||
:class="['tool-item', activeTool === 'CircularBrush' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
:class="['tool-item', activeTool === 'CircularBrush' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
@click.prevent="setToolActive('CircularBrush')">
|
@click.prevent="setToolActive('CircularBrush')">
|
||||||
<svg-icon icon-class="circularbrush" class="svg-icon" />
|
<svg-icon icon-class="circularbrush" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<div :class="['tool-item', activeTool === 'CircularEraser' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
<div :class="['tool-item', activeTool === 'CircularEraser' && segmentList.length > 0 ? 'tool-item-active' : '']"
|
||||||
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) ? 'not-allowed' : 'pointer' }"
|
:style="{ cursor: segmentList.length <= 0 || (curSegment && curSegment.lock) || ['viewport-MPR-1', 'viewport-MPR-2'].includes(`${viewportKey}-${activeViewportIndex}`) ? 'not-allowed' : 'pointer' }"
|
||||||
:title="$t('trials:Segmentations:tools:Eraser')" @click.prevent="setToolActive('CircularEraser')">
|
:title="$t('trials:Segmentations:tools:Eraser')"
|
||||||
|
@click.prevent="setToolActive('CircularEraser')">
|
||||||
<svg-icon icon-class="clear" class="svg-icon" />
|
<svg-icon icon-class="clear" class="svg-icon" />
|
||||||
</div>
|
</div>
|
||||||
<!-- <div :class="['tool-item']">
|
<!-- <div :class="['tool-item']">
|
||||||
|
|
@ -79,7 +80,8 @@
|
||||||
@click.stop="changeShowSegmentConfig" />
|
@click.stop="changeShowSegmentConfig" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<div class="addSegmentBox viewHover" @click.stop="addSegment" v-if="segmentList.length <= 0">
|
<div class="addSegmentBox viewHover" @click.stop="addSegment"
|
||||||
|
v-if="segmentList.length <= 0 && readingTaskState < 2">
|
||||||
<span><i class="el-icon-plus"></i>
|
<span><i class="el-icon-plus"></i>
|
||||||
{{ $t('trials:reading:Segmentations:button:addSegmention') }}
|
{{ $t('trials:reading:Segmentations:button:addSegmention') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -123,16 +125,11 @@
|
||||||
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
|
$t('trials:reading:Segmentations:title:InactiveSegmentationsShow')
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="SegmentConfig" v-if="SegmentConfig.InactiveSegmentations.show">
|
|
||||||
<span>{{ $t('trials:reading:Segmentations:title:Opacity') }}</span>
|
|
||||||
<el-slider v-model="SegmentConfig.InactiveSegmentations.fillAlpha" show-input :step="0.1"
|
|
||||||
:max="1" input-size="mini" :show-input-controls="false" />
|
|
||||||
</div> -->
|
|
||||||
</div>
|
</div>
|
||||||
<template v-if="segmentList.length > 0">
|
<template v-if="segmentList.length > 0">
|
||||||
<div class="SegmentGroupBox">
|
<div class="SegmentGroupBox">
|
||||||
<div style="display: flex;align-items: center;">
|
<div style="display: flex;align-items: center;">
|
||||||
<el-popover placement="left" width="40" trigger="click">
|
<el-popover placement="left" width="40" trigger="click" v-if="readingTaskState < 2">
|
||||||
<div class="SegmentGroupBtnBox">
|
<div class="SegmentGroupBtnBox">
|
||||||
<div class="SegmentGroupBtn" @click.stop="addSegmentGroup">
|
<div class="SegmentGroupBtn" @click.stop="addSegmentGroup">
|
||||||
{{ $t('trials:reading:Segmentations:button:addSegmentGroup') }}
|
{{ $t('trials:reading:Segmentations:button:addSegmentGroup') }}
|
||||||
|
|
@ -149,13 +146,14 @@
|
||||||
</div>
|
</div>
|
||||||
<i slot="reference" class="el-icon-more" style="cursor: pointer;color:#fff" />
|
<i slot="reference" class="el-icon-more" style="cursor: pointer;color:#fff" />
|
||||||
</el-popover>
|
</el-popover>
|
||||||
<el-select v-model="segmentationId" placeholder="" @change="selectSegmentGroup()">
|
<el-select v-model="segmentationId" placeholder="" @change="selectSegmentGroup()"
|
||||||
|
:disabled="saveLoading">
|
||||||
<el-option v-for="item in segmentList" :key="`${item.segmentationId}`"
|
<el-option v-for="item in segmentList" :key="`${item.segmentationId}`"
|
||||||
:label="item.name" :value="item.segmentationId">
|
:label="item.name" :value="item.segmentationId">
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex;align-items: center;">
|
<div style="display: flex;align-items: center;" v-if="readingTaskState < 2">
|
||||||
<i class="el-icon-warning-outline" style="color:red;margin-right: 5px;"
|
<i class="el-icon-warning-outline" style="color:red;margin-right: 5px;"
|
||||||
:title="$t('trials:reading:Segmentations:tip:segmentationIsNotSave')"
|
:title="$t('trials:reading:Segmentations:tip:segmentationIsNotSave')"
|
||||||
v-if="!curSegmentGroup.isSaved"></i>
|
v-if="!curSegmentGroup.isSaved"></i>
|
||||||
|
|
@ -166,7 +164,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="addSegmentBox" @click.stop="addSegment"
|
<div class="addSegmentBox" @click.stop="addSegment"
|
||||||
style="display: flex;align-items: center;justify-content: space-between;">
|
style="display: flex;align-items: center;justify-content: space-between;"
|
||||||
|
v-if="readingTaskState < 2">
|
||||||
<span><i class="el-icon-plus"></i>
|
<span><i class="el-icon-plus"></i>
|
||||||
{{ $t('trials:reading:Segmentations:button:addSegment') }}
|
{{ $t('trials:reading:Segmentations:button:addSegment') }}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -219,7 +218,7 @@
|
||||||
<i class="el-icon-lock" v-if="item.lock" @click.stop="lockSegment(item, false)"></i>
|
<i class="el-icon-lock" v-if="item.lock" @click.stop="lockSegment(item, false)"></i>
|
||||||
<el-popover placement="bottom" width="40" trigger="click" class="docShow"
|
<el-popover placement="bottom" width="40" trigger="click" class="docShow"
|
||||||
:value="popoverId === `popover-${item.segmentationId}_${item.segmentIndex}`"
|
:value="popoverId === `popover-${item.segmentationId}_${item.segmentIndex}`"
|
||||||
@show="handleClickPopover(item)">
|
@show="handleClickPopover(item)" v-if="readingTaskState < 2">
|
||||||
<div class="SegmentGroupBtnBox">
|
<div class="SegmentGroupBtnBox">
|
||||||
<div class="SegmentGroupBtn" @click.stop="rename('segment', item)">
|
<div class="SegmentGroupBtn" @click.stop="rename('segment', item)">
|
||||||
{{ $t('trials:reading:Segmentations:button:renameSegmentGroup') }}
|
{{ $t('trials:reading:Segmentations:button:renameSegmentGroup') }}
|
||||||
|
|
@ -244,7 +243,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
<div class="saveBtnBox">
|
<div class="saveBtnBox" v-if="readingTaskState < 2">
|
||||||
<el-button type="success" size="small" :disabled="saveLoading" @click="saveSegmentGroup()">
|
<el-button type="success" size="small" :disabled="saveLoading" @click="saveSegmentGroup()">
|
||||||
{{ $t("trials:reading:Segmentations:button:saveAll") }}
|
{{ $t("trials:reading:Segmentations:button:saveAll") }}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
|
@ -260,6 +259,8 @@ import * as cornerstoneAdapters from "@cornerstonejs/adapters";
|
||||||
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'
|
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'
|
||||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
import { getCustomizeStandardsSegmentDicomTools } from './toolConfig'
|
import { getCustomizeStandardsSegmentDicomTools } from './toolConfig'
|
||||||
|
import * as polySeg from '@cornerstonejs/polymorphic-segmentation'
|
||||||
|
cornerstoneTools.init({ addons: { polySeg } })
|
||||||
const {
|
const {
|
||||||
ToolGroupManager,
|
ToolGroupManager,
|
||||||
Enums: csToolsEnums,
|
Enums: csToolsEnums,
|
||||||
|
|
@ -270,6 +271,7 @@ const {
|
||||||
CrosshairsTool,
|
CrosshairsTool,
|
||||||
utilities: CStUtils,
|
utilities: CStUtils,
|
||||||
} = cornerstoneTools;
|
} = cornerstoneTools;
|
||||||
|
|
||||||
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||||
const { segmentation: segmentationUtils } = CStUtils;
|
const { segmentation: segmentationUtils } = CStUtils;
|
||||||
const { cache, getRenderingEngine, imageLoader, eventTarget, metaData, utilities: csUtils, volumeLoader } = cornerstone;
|
const { cache, getRenderingEngine, imageLoader, eventTarget, metaData, utilities: csUtils, volumeLoader } = cornerstone;
|
||||||
|
|
@ -304,12 +306,38 @@ export default {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
SegmentConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
actionConfiguration: {
|
actionConfiguration: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => {
|
default: () => {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
curSegSeries: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
trialCriterion: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
segId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
segIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
renderingEngineId: {
|
renderingEngineId: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
|
|
@ -321,6 +349,10 @@ export default {
|
||||||
globalLoading: {
|
globalLoading: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
histogramVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -338,16 +370,6 @@ export default {
|
||||||
ThresholdTools: ['ThresholdCircle', 'ThresholdSphere'],
|
ThresholdTools: ['ThresholdCircle', 'ThresholdSphere'],
|
||||||
thresholdType: null,
|
thresholdType: null,
|
||||||
showSegmentConfig: false,
|
showSegmentConfig: false,
|
||||||
SegmentConfig: {
|
|
||||||
renderOutline: true,
|
|
||||||
renderFill: true,
|
|
||||||
fillAlpha: 0.5,
|
|
||||||
outlineWidth: 1,
|
|
||||||
InactiveSegmentations: {
|
|
||||||
show: true,
|
|
||||||
fillAlpha: 0.3,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
segmentList: [],
|
segmentList: [],
|
||||||
segmentationId: "",
|
segmentationId: "",
|
||||||
segmentIndex: null,
|
segmentIndex: null,
|
||||||
|
|
@ -363,7 +385,7 @@ export default {
|
||||||
'#ff994d',
|
'#ff994d',
|
||||||
'#fb628b',
|
'#fb628b',
|
||||||
],
|
],
|
||||||
viewprotIds: ['viewport-0', 'viewport-1', 'viewport-2', 'viewport-3', 'viewport-MPR-0', 'viewport-MPR-1', 'viewport-MPR-2'], //
|
viewportIds: [], //
|
||||||
statsKey: [],
|
statsKey: [],
|
||||||
drawing: false, // 是否正在分割
|
drawing: false, // 是否正在分割
|
||||||
// isDel: false,
|
// isDel: false,
|
||||||
|
|
@ -383,14 +405,30 @@ export default {
|
||||||
this.segmentationModifiedCallback
|
this.segmentationModifiedCallback
|
||||||
);
|
);
|
||||||
DicomEvent.$on('activeSeries', (series) => {
|
DicomEvent.$on('activeSeries', (series) => {
|
||||||
|
console.log(series, 'series')
|
||||||
|
let { TaskInfo = {}, Id } = series
|
||||||
|
if (this.isMPR) return false
|
||||||
|
if (Id === this.series.Id && TaskInfo.VisitTaskId === this.visitInfo.VisitTaskId) return false
|
||||||
this.series = series
|
this.series = series
|
||||||
|
this.$emit("update:curSegSeries", Object.assign(series, {}))
|
||||||
|
this.getSegmentationList()
|
||||||
})
|
})
|
||||||
DicomEvent.$on('isloaded', (data) => {
|
DicomEvent.$on('isloaded', (data) => {
|
||||||
if (this.isloaded) return false
|
let { segment, isChange = true, viewportId, series } = data
|
||||||
this.isloaded = true
|
DicomEvent.$emit('renderSegmentation', viewportId)
|
||||||
let { segment, isChange = true } = data
|
})
|
||||||
this.delAllSegment(isChange)
|
DicomEvent.$on('SegmentationLoading', (viewportId) => {
|
||||||
this.getSegmentationList(segment)
|
if (viewportId !== `${this.viewportKey}-${this.activeViewportIndex}`) return false
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
DicomEvent.$on('changeMPR', () => {
|
||||||
|
if (this.loading) return false
|
||||||
|
// if (viewportId !== `${this.viewportKey}-${this.activeViewportIndex}`) return false
|
||||||
|
if (this.segmentList && this.segmentList.length > 0) {
|
||||||
|
this.segmentationId = this.segmentList[0].segmentationId
|
||||||
|
this.segmentIndex = this.segmentList[0] ? this.segmentList[0].segments[0].segmentIndex : null
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||||
|
|
@ -409,12 +447,15 @@ export default {
|
||||||
s = this.curSegmentGroup.segments.find(item => item.segmentIndex === this.segmentIndex)
|
s = this.curSegmentGroup.segments.find(item => item.segmentIndex === this.segmentIndex)
|
||||||
}
|
}
|
||||||
return s
|
return s
|
||||||
|
},
|
||||||
|
readingTaskState() {
|
||||||
|
return this.series.TaskInfo ? this.series.TaskInfo.ReadingTaskState : 0
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
SegmentConfig: {
|
SegmentConfig: {
|
||||||
handler() {
|
handler() {
|
||||||
this.readingSegmentByConfig()
|
// this.readingSegmentByConfig()
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
},
|
},
|
||||||
|
|
@ -429,9 +470,23 @@ export default {
|
||||||
this.setBrushThreshold()
|
this.setBrushThreshold()
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
|
},
|
||||||
|
segmentIndex() {
|
||||||
|
this.$emit('update:segIndex', this.segmentIndex)
|
||||||
|
},
|
||||||
|
segmentationId() {
|
||||||
|
this.$emit('update:segId', this.segmentationId)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
showSurface(item) {
|
||||||
|
this.$emit("showSurface", {
|
||||||
|
segmentationId: item.segmentationId,
|
||||||
|
segmentIndex: item.segmentIndex,
|
||||||
|
volumeId: this.series.SeriesInstanceUid,
|
||||||
|
segmentations: this.curSegmentGroup
|
||||||
|
})
|
||||||
|
},
|
||||||
handleClickPopover(item) {
|
handleClickPopover(item) {
|
||||||
this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}`
|
this.popoverId = `popover-${item.segmentationId}_${item.segmentIndex}`
|
||||||
},
|
},
|
||||||
|
|
@ -499,7 +554,6 @@ export default {
|
||||||
segmentationId: list[0].segmentationId,
|
segmentationId: list[0].segmentationId,
|
||||||
segmentIndices: list.map(item => item.segmentIndex),
|
segmentIndices: list.map(item => item.segmentIndex),
|
||||||
});
|
});
|
||||||
console.log(bidirectionalData, list[0].segmentationId, 'bidirectionalData')
|
|
||||||
if (bidirectionalData.length <= 0) {
|
if (bidirectionalData.length <= 0) {
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
let annotations = annotation.state.getAllAnnotations().filter(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex);
|
let annotations = annotation.state.getAllAnnotations().filter(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex);
|
||||||
|
|
@ -558,8 +612,11 @@ export default {
|
||||||
|
|
||||||
},
|
},
|
||||||
setToolActive(toolName) {
|
setToolActive(toolName) {
|
||||||
|
// if (!this.series.TaskInfo || this.series.TaskInfo.VisitTaskId !== this.visitInfo.VisitTaskId) return false
|
||||||
if (this.segmentList.length <= 0) return false
|
if (this.segmentList.length <= 0) return false
|
||||||
if (this.curSegment.lock) return false
|
if (this.curSegment.lock) return false
|
||||||
|
if (this.histogramVisible && !this.ThresholdTools.includes(toolName)) return false
|
||||||
|
if (['viewport-MPR-1', 'viewport-MPR-2'].includes(`${this.viewportKey}-${this.activeViewportIndex}`)) return false
|
||||||
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
const toolGroupId = this.isMPR ? this.volumeToolGroupId : `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId)
|
||||||
if (this.activeTool === toolName) {
|
if (this.activeTool === toolName) {
|
||||||
|
|
@ -596,71 +653,33 @@ export default {
|
||||||
viewBidirectional(arr, view) {
|
viewBidirectional(arr, view) {
|
||||||
for (let j = 0; j < arr.length; j++) {
|
for (let j = 0; j < arr.length; j++) {
|
||||||
let item = arr[j]
|
let item = arr[j]
|
||||||
let bidirectional = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
|
||||||
item.bidirectionalView = view
|
item.bidirectionalView = view
|
||||||
if (!bidirectional) continue
|
// let bidirectional = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
annotation.visibility.setAnnotationVisibility(bidirectional.annotationUID, view)
|
// item.bidirectionalView = view
|
||||||
|
// if (!bidirectional) continue
|
||||||
|
// annotation.visibility.setAnnotationVisibility(bidirectional.annotationUID, view)
|
||||||
}
|
}
|
||||||
this.resetViewport()
|
DicomEvent.$emit('viewBidirectional', arr)
|
||||||
|
// this.resetViewport()
|
||||||
},
|
},
|
||||||
async jumpBidirectional(item) {
|
async jumpBidirectional(item) {
|
||||||
if (item.bidirectional) {
|
DicomEvent.$emit('jumpBidirectional', item)
|
||||||
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
|
||||||
console.log(an, 'an')
|
|
||||||
if (!an) return false
|
|
||||||
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
|
||||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
|
||||||
const viewport = renderingEngine.getViewport(viewportId)
|
|
||||||
let key = Object.keys(an.data.cachedStats)[0]; // referencedImageId
|
|
||||||
if (key) {
|
|
||||||
let sliceIndex = key.split("?")[1].split("&")[0].split("=")[1]
|
|
||||||
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIndex });
|
|
||||||
} else {
|
|
||||||
const points = an.data.handles.points;
|
|
||||||
const worldPoint = points[0]; // 取一个点
|
|
||||||
let volume = cache.getVolume(this.series.SeriesInstanceUid)
|
|
||||||
let { imageData, numFrames } = volume
|
|
||||||
const ijk = imageData.worldToIndex(worldPoint);
|
|
||||||
const sliceIndex = Math.abs(Math.round(ijk[2]));
|
|
||||||
// console.log(sliceIndex, 'sliceIndex')
|
|
||||||
csUtils.jumpToSlice(viewport.element, { imageIndex: numFrames - sliceIndex - 1 });
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
viewSegmentGroup(item) {
|
viewSegmentGroup(item) {
|
||||||
let view = !item.view
|
item.view = !item.view
|
||||||
this.viewprotIds.forEach(id => {
|
|
||||||
segmentation.config.visibility.setSegmentationRepresentationVisibility(
|
|
||||||
id,
|
|
||||||
{
|
|
||||||
segmentationId: item.segmentationId,
|
|
||||||
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
|
||||||
},
|
|
||||||
view
|
|
||||||
);
|
|
||||||
})
|
|
||||||
item.view = view
|
|
||||||
|
|
||||||
item.segments.forEach(i => {
|
item.segments.forEach(i => {
|
||||||
i.view = view
|
i.view = item.view
|
||||||
// this.viewBidirectional(i, view)
|
|
||||||
})
|
})
|
||||||
this.viewBidirectional(item.segments, view)
|
DicomEvent.$emit('viewSegmentation', item)
|
||||||
|
// this.viewBidirectional(item.segments, view)
|
||||||
},
|
},
|
||||||
viewSegment(item, view) {
|
viewSegment(item, view) {
|
||||||
this.viewprotIds.forEach(id => {
|
|
||||||
segmentation.config.visibility.setSegmentIndexVisibility(id, {
|
|
||||||
segmentationId: item.segmentationId,
|
|
||||||
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
|
||||||
}, item.segmentIndex, view)
|
|
||||||
})
|
|
||||||
item.view = view
|
item.view = view
|
||||||
this.viewBidirectional([item], view)
|
|
||||||
this.$emit('setToolsPassive')
|
this.$emit('setToolsPassive')
|
||||||
|
DicomEvent.$emit('viewSegment', item)
|
||||||
},
|
},
|
||||||
lockSegment(item, lock) {
|
lockSegment(item, lock) {
|
||||||
|
if (this.readingTaskState >= 2) return false
|
||||||
segmentation.segmentLocking.setSegmentIndexLocked(item.segmentationId, item.segmentIndex, lock)
|
segmentation.segmentLocking.setSegmentIndexLocked(item.segmentationId, item.segmentIndex, lock)
|
||||||
item.lock = lock
|
item.lock = lock
|
||||||
if (!lock) this.changeSegmentationSavedStatus(item.segmentationId, lock)
|
if (!lock) this.changeSegmentationSavedStatus(item.segmentationId, lock)
|
||||||
|
|
@ -670,7 +689,7 @@ export default {
|
||||||
this.segmentationId = item.segmentationId;
|
this.segmentationId = item.segmentationId;
|
||||||
this.segmentIndex = item.segmentIndex;
|
this.segmentIndex = item.segmentIndex;
|
||||||
}
|
}
|
||||||
segmentation.segmentIndex.setActiveSegmentIndex(item.segmentationId, item.segmentIndex);
|
// segmentation.segmentIndex.setActiveSegmentIndex(item.segmentationId, item.segmentIndex);
|
||||||
if (isChange) { this.jumpBidirectional(item) }
|
if (isChange) { this.jumpBidirectional(item) }
|
||||||
|
|
||||||
if (item.lock) {
|
if (item.lock) {
|
||||||
|
|
@ -679,30 +698,57 @@ export default {
|
||||||
// this.resetViewport()
|
// this.resetViewport()
|
||||||
},
|
},
|
||||||
selectSegmentGroup(s) {
|
selectSegmentGroup(s) {
|
||||||
this.viewprotIds.forEach(id => {
|
// segmentation.activeSegmentation.setActiveSegmentation(`${this.viewportKey}-${this.activeViewportIndex}`, this.segmentationId)
|
||||||
segmentation.activeSegmentation.setActiveSegmentation(id, this.segmentationId)
|
this.$emit('setToolsPassive')
|
||||||
})
|
this.segmentIndex = null;
|
||||||
let segment = s ? s : this.segmentList.find(item => item.segmentationId === this.segmentationId).segments[0]
|
let segment = s ? s : this.segmentList.find(item => item.segmentationId === this.segmentationId).segments[0]
|
||||||
this.selectSegment(segment, s ? false : true)
|
this.$nextTick(() => {
|
||||||
this.readingSegmentByConfig()
|
this.selectSegment(segment)
|
||||||
|
})
|
||||||
|
// this.segmentIndex = segment.segmentIndex
|
||||||
|
// this.selectSegment(segment, s ? false : true)
|
||||||
|
// this.readingSegmentByConfig()
|
||||||
|
},
|
||||||
|
getSegmentationName(num = 1) {
|
||||||
|
let defaultSegmentationName = this.trialCriterion.DefaultSegmentName.SegmentationName
|
||||||
|
let name = defaultSegmentationName
|
||||||
|
let has = this.segmentList.find(item => item.name === name)
|
||||||
|
if (has) {
|
||||||
|
name = defaultSegmentationName + num
|
||||||
|
has = this.segmentList.find(item => item.name === name)
|
||||||
|
num++
|
||||||
|
if (has) name = this.getSegmentationName(num)
|
||||||
|
}
|
||||||
|
return name
|
||||||
|
},
|
||||||
|
getSegmentName(arr, num = 1) {
|
||||||
|
let defaultSegmentName = arr[0].SegmentLabel
|
||||||
|
let name = defaultSegmentName + num
|
||||||
|
let has = arr.find(item => item.SegmentLabel === name)
|
||||||
|
num++
|
||||||
|
if (has) name = this.getSegmentName(arr, num)
|
||||||
|
return name
|
||||||
},
|
},
|
||||||
async addSegmentGroup() {
|
async addSegmentGroup() {
|
||||||
let viewprotIds = this.viewprotIds
|
|
||||||
// let segmentationId = this.$guid();
|
// let segmentationId = this.$guid();
|
||||||
let obj = {
|
let obj = {
|
||||||
name: this.$t('trials:reading:Segmentations:name:SegmentGroup') + (this.segmentList.length + 1),
|
name: this.getSegmentationName(),
|
||||||
view: true,
|
view: true,
|
||||||
segmentationId: null,
|
segmentationId: null,
|
||||||
isSaved: false,
|
isSaved: false,
|
||||||
segments: []
|
segments: []
|
||||||
}
|
}
|
||||||
|
this.segmentIndex = null
|
||||||
let segmentationId = await this.addOrUpdateSegmentation({ name: obj.name })
|
let segmentationId = await this.addOrUpdateSegmentation({ name: obj.name })
|
||||||
obj.segmentationId = segmentationId
|
obj.segmentationId = segmentationId
|
||||||
|
await this.createSegmentation(obj.segmentationId)
|
||||||
|
this.createSegmentationRepresentation(obj.segmentationId)
|
||||||
|
this.trialCriterion.DefaultSegmentName.SegmentNameList.forEach(async (SegmentName, index) => {
|
||||||
let o = {
|
let o = {
|
||||||
segmentIndex: 1,
|
segmentIndex: index + 1,
|
||||||
segmentationId,
|
segmentationId,
|
||||||
SegmentLabel: 'Segment 1',
|
SegmentLabel: SegmentName,
|
||||||
color: this.colors[0],
|
color: this.colors[index],
|
||||||
stats: null,
|
stats: null,
|
||||||
bidirectional: null,
|
bidirectional: null,
|
||||||
bidirectionalView: true,
|
bidirectionalView: true,
|
||||||
|
|
@ -711,33 +757,42 @@ export default {
|
||||||
}
|
}
|
||||||
let id = await this.addOrUpdateSegment({ name: o.SegmentLabel, color: o.color, segmentIndex: o.segmentIndex, segmentationId: o.segmentationId })
|
let id = await this.addOrUpdateSegment({ name: o.SegmentLabel, color: o.color, segmentIndex: o.segmentIndex, segmentationId: o.segmentationId })
|
||||||
o.id = id
|
o.id = id
|
||||||
obj.segments.push(o);
|
obj.segments.splice(index, 0, o);
|
||||||
|
segmentation.segmentIndex.setActiveSegmentIndex(obj.segmentationId, index + 1);
|
||||||
|
this.changeColor(this.colors[index], { segmentationId: obj.segmentationId, segmentIndex: index + 1, color: this.colors[index] })
|
||||||
|
if (index === this.trialCriterion.DefaultSegmentName.SegmentNameList.length - 1) {
|
||||||
|
segmentation.segmentIndex.setActiveSegmentIndex(obj.segmentationId, 1);
|
||||||
|
}
|
||||||
|
})
|
||||||
this.segmentList.push(obj);
|
this.segmentList.push(obj);
|
||||||
this.segmentationId = obj.segmentationId;
|
this.segmentationId = obj.segmentationId;
|
||||||
await this.createSegmentation(obj.segmentationId)
|
|
||||||
this.createSegmentationRepresentation(obj.segmentationId)
|
|
||||||
this.segmentIndex = 1
|
this.segmentIndex = 1
|
||||||
viewprotIds.forEach(id => {
|
// segmentation.segmentIndex.setActiveSegmentIndex(this.segmentationId, 1);
|
||||||
segmentation.config.color.setSegmentIndexColor(id, obj.segmentationId, 1, this.hex2Rgb(this.colors[0]))
|
// viewportIds.forEach(id => {
|
||||||
})
|
// segmentation.config.color.setSegmentIndexColor(id, obj.segmentationId, 1, this.hex2Rgb(this.colors[0]))
|
||||||
this.selectSegmentGroup()
|
// })
|
||||||
|
// this.selectSegmentGroup()
|
||||||
},
|
},
|
||||||
async addSegment() {
|
async addSegment() {
|
||||||
let viewprotIds = this.viewprotIds;
|
if (this.saveLoading) return false
|
||||||
if (this.segmentList.length <= 0) {
|
if (this.segmentList.length <= 0) {
|
||||||
let obj = {
|
let obj = {
|
||||||
name: this.$t('trials:reading:Segmentations:name:SegmentGroup') + 1,
|
name: this.getSegmentationName(),
|
||||||
view: true,
|
view: true,
|
||||||
isSaved: false,
|
isSaved: false,
|
||||||
segments: []
|
segments: []
|
||||||
}
|
}
|
||||||
|
this.segmentIndex = null
|
||||||
let segmentationId = await this.addOrUpdateSegmentation({ name: obj.name })
|
let segmentationId = await this.addOrUpdateSegmentation({ name: obj.name })
|
||||||
obj.segmentationId = segmentationId
|
obj.segmentationId = segmentationId
|
||||||
|
await this.createSegmentation(segmentationId)
|
||||||
|
this.createSegmentationRepresentation(segmentationId)
|
||||||
|
this.trialCriterion.DefaultSegmentName.SegmentNameList.forEach(async (SegmentName, index) => {
|
||||||
let o = {
|
let o = {
|
||||||
segmentIndex: 1,
|
segmentIndex: index + 1,
|
||||||
segmentationId,
|
segmentationId,
|
||||||
SegmentLabel: 'Segment 1',
|
SegmentLabel: SegmentName,
|
||||||
color: this.colors[0],
|
color: this.colors[index],
|
||||||
stats: null,
|
stats: null,
|
||||||
bidirectional: null,
|
bidirectional: null,
|
||||||
bidirectionalView: true,
|
bidirectionalView: true,
|
||||||
|
|
@ -746,17 +801,22 @@ export default {
|
||||||
}
|
}
|
||||||
let id = await this.addOrUpdateSegment({ name: o.SegmentLabel, color: o.color, segmentIndex: o.segmentIndex, segmentationId: o.segmentationId })
|
let id = await this.addOrUpdateSegment({ name: o.SegmentLabel, color: o.color, segmentIndex: o.segmentIndex, segmentationId: o.segmentationId })
|
||||||
o.id = id
|
o.id = id
|
||||||
obj.segments.push(o);
|
obj.segments.splice(index, 0, o);
|
||||||
this.segmentList.push(obj);
|
segmentation.segmentIndex.setActiveSegmentIndex(obj.segmentationId, index + 1);
|
||||||
this.segmentationId = this.segmentList[0].segmentationId;
|
this.changeColor(this.colors[index], { segmentationId: obj.segmentationId, segmentIndex: index + 1, color: this.colors[index] })
|
||||||
await this.createSegmentation(this.segmentationId)
|
if (index === this.trialCriterion.DefaultSegmentName.SegmentNameList.length - 1) {
|
||||||
this.createSegmentationRepresentation(this.segmentationId)
|
segmentation.segmentIndex.setActiveSegmentIndex(obj.segmentationId, 1);
|
||||||
this.segmentIndex = 1
|
}
|
||||||
segmentation.segmentIndex.setActiveSegmentIndex(this.segmentList[0].segmentationId, 1);
|
|
||||||
viewprotIds.forEach(id => {
|
|
||||||
segmentation.config.color.setSegmentIndexColor(id, this.segmentList[0].segmentationId, 1, this.hex2Rgb(this.colors[0]))
|
|
||||||
})
|
})
|
||||||
this.readingSegmentByConfig()
|
this.segmentList.push(obj);
|
||||||
|
this.segmentationId = segmentationId;
|
||||||
|
this.segmentIndex = 1
|
||||||
|
// segmentation.segmentIndex.setActiveSegmentIndex(this.segmentList[0].segmentationId, 1);
|
||||||
|
// this.changeColor(this.colors[0], { segmentationId: this.segmentList[0].segmentationId, segmentIndex: 1, color: this.colors[0] })
|
||||||
|
// viewportIds.forEach(id => {
|
||||||
|
// segmentation.config.color.setSegmentIndexColor(id, this.segmentList[0].segmentationId, 1, this.hex2Rgb(this.colors[0]))
|
||||||
|
// })
|
||||||
|
// this.readingSegmentByConfig()
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
let item = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
let item = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
||||||
|
|
@ -765,7 +825,7 @@ export default {
|
||||||
let obj = {
|
let obj = {
|
||||||
segmentIndex: segmentIndex,
|
segmentIndex: segmentIndex,
|
||||||
segmentationId: this.segmentationId,
|
segmentationId: this.segmentationId,
|
||||||
SegmentLabel: `Segment ${segmentIndex}`,
|
SegmentLabel: this.getSegmentName(item.segments),
|
||||||
color: item.segments.length >= this.colors.length ? this.colors[0] : this.colors[item.segments.length],
|
color: item.segments.length >= this.colors.length ? this.colors[0] : this.colors[item.segments.length],
|
||||||
stats: null,
|
stats: null,
|
||||||
bidirectional: null,
|
bidirectional: null,
|
||||||
|
|
@ -781,19 +841,22 @@ export default {
|
||||||
let id = await this.addOrUpdateSegment({ name: obj.SegmentLabel, color: obj.color, segmentIndex: obj.segmentIndex, segmentationId: obj.segmentationId })
|
let id = await this.addOrUpdateSegment({ name: obj.SegmentLabel, color: obj.color, segmentIndex: obj.segmentIndex, segmentationId: obj.segmentationId })
|
||||||
obj.id = id
|
obj.id = id
|
||||||
item.segments.push(obj)
|
item.segments.push(obj)
|
||||||
segmentation.segmentIndex.setActiveSegmentIndex(obj.segmentationId, obj.segmentIndex);
|
|
||||||
viewprotIds.forEach(id => {
|
|
||||||
segmentation.config.color.setSegmentIndexColor(id, obj.segmentationId, obj.segmentIndex, this.hex2Rgb(obj.color))
|
|
||||||
})
|
|
||||||
this.segmentIndex = obj.segmentIndex
|
this.segmentIndex = obj.segmentIndex
|
||||||
|
// segmentation.segmentIndex.setActiveSegmentIndex(obj.segmentationId, obj.segmentIndex);
|
||||||
|
this.changeColor(obj.color, { segmentationId: obj.segmentationId, segmentIndex: obj.segmentIndex, color: obj.color })
|
||||||
|
// viewportIds.forEach(id => {
|
||||||
|
// segmentation.config.color.setSegmentIndexColor(id, obj.segmentationId, obj.segmentIndex, this.hex2Rgb(obj.color))
|
||||||
|
// })
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
},
|
},
|
||||||
changeColor(e, item) {
|
changeColor(e, item) {
|
||||||
this.viewprotIds.forEach(id => {
|
DicomEvent.$emit('changeColor', item)
|
||||||
segmentation.config.color.setSegmentIndexColor(id, item.segmentationId, item.segmentIndex, this.hex2Rgb(e))
|
// this.viewportIds.forEach(id => {
|
||||||
})
|
// segmentation.config.color.setSegmentIndexColor(id, item.segmentationId, item.segmentIndex, this.hex2Rgb(e))
|
||||||
|
// })
|
||||||
},
|
},
|
||||||
// 清空所有分割
|
// 清空所有分割
|
||||||
delAllSegment(isChange) {
|
delAllSegment(isChange) {
|
||||||
|
|
@ -830,12 +893,13 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.segmentationId = ''
|
this.segmentationId = ''
|
||||||
}
|
}
|
||||||
this.readingSegmentByConfig()
|
// this.readingSegmentByConfig()
|
||||||
this.resetViewport()
|
this.resetViewport()
|
||||||
this.$emit('resetQuestion')
|
this.$emit('resetQuestion')
|
||||||
},
|
},
|
||||||
// 删除分割片段
|
// 删除分割片段
|
||||||
async delSegment(data) {
|
async delSegment(data) {
|
||||||
|
this.popoverId = null;
|
||||||
let segmentIndex = data.segmentIndex
|
let segmentIndex = data.segmentIndex
|
||||||
let confirm = await this.$confirm(this.$t('trials:reading:Segmentations:confirm:delSegment'))
|
let confirm = await this.$confirm(this.$t('trials:reading:Segmentations:confirm:delSegment'))
|
||||||
if (!confirm) return false
|
if (!confirm) return false
|
||||||
|
|
@ -862,15 +926,18 @@ export default {
|
||||||
|
|
||||||
},
|
},
|
||||||
resetViewport(passive = true) {
|
resetViewport(passive = true) {
|
||||||
let renderingEngine = getRenderingEngine(this.renderingEngineId)
|
DicomEvent.$emit('resetViewport')
|
||||||
this.viewprotIds.forEach(id => {
|
|
||||||
const viewport = renderingEngine.getViewport(id)
|
|
||||||
viewport.render()
|
|
||||||
})
|
|
||||||
if (passive) this.$emit('setToolsPassive')
|
if (passive) this.$emit('setToolsPassive')
|
||||||
},
|
},
|
||||||
async rename(key, item) {
|
async rename(key, item) {
|
||||||
let name = await this.customPrompt()
|
let value = null
|
||||||
|
if (key === 'segmentGroup') {
|
||||||
|
let group = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
||||||
|
value = group.name
|
||||||
|
} else {
|
||||||
|
value = item.SegmentLabel
|
||||||
|
}
|
||||||
|
let name = await this.customPrompt(value)
|
||||||
if (!name) return false
|
if (!name) return false
|
||||||
if (key === 'segmentGroup') {
|
if (key === 'segmentGroup') {
|
||||||
let group = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
let group = this.segmentList.find(i => i.segmentationId === this.segmentationId)
|
||||||
|
|
@ -881,7 +948,7 @@ export default {
|
||||||
this.addOrUpdateSegment({ name: item.SegmentLabel, color: item.color, segmentIndex: item.segmentIndex, segmentationId: item.segmentationId, segmentJson: JSON.stringify({ stats: item.stats, bidirectional: item.bidirectional }), id: item.id })
|
this.addOrUpdateSegment({ name: item.SegmentLabel, color: item.color, segmentIndex: item.segmentIndex, segmentationId: item.segmentationId, segmentJson: JSON.stringify({ stats: item.stats, bidirectional: item.bidirectional }), id: item.id })
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async customPrompt() {
|
async customPrompt(name) {
|
||||||
try {
|
try {
|
||||||
const that = this
|
const that = this
|
||||||
// 请输入标记名称
|
// 请输入标记名称
|
||||||
|
|
@ -893,6 +960,7 @@ export default {
|
||||||
showCancelButton: true,
|
showCancelButton: true,
|
||||||
closeOnClickModal: false,
|
closeOnClickModal: false,
|
||||||
closeOnPressEscape: false,
|
closeOnPressEscape: false,
|
||||||
|
inputValue: name,
|
||||||
beforeClose: (action, instance, done) => {
|
beforeClose: (action, instance, done) => {
|
||||||
if (action === 'confirm') {
|
if (action === 'confirm') {
|
||||||
// const value = instance.inputValue
|
// const value = instance.inputValue
|
||||||
|
|
@ -911,7 +979,7 @@ export default {
|
||||||
// 切换非当前分组分割标记显示
|
// 切换非当前分组分割标记显示
|
||||||
changeInactiveSegmentShow() {
|
changeInactiveSegmentShow() {
|
||||||
let segmentList = this.segmentList.filter(item => item.segmentationId !== this.segmentationId)
|
let segmentList = this.segmentList.filter(item => item.segmentationId !== this.segmentationId)
|
||||||
this.viewprotIds.forEach(id => {
|
this.viewportIds.forEach(id => {
|
||||||
segmentation.config.visibility.setSegmentationRepresentationVisibility(
|
segmentation.config.visibility.setSegmentationRepresentationVisibility(
|
||||||
id,
|
id,
|
||||||
{
|
{
|
||||||
|
|
@ -953,6 +1021,7 @@ export default {
|
||||||
this.exportSegmentation(this.segmentationId, group, true)
|
this.exportSegmentation(this.segmentationId, group, true)
|
||||||
},
|
},
|
||||||
exportSegmentation(segmentationId, group, isFile = false) {
|
exportSegmentation(segmentationId, group, isFile = false) {
|
||||||
|
try {
|
||||||
const segmentationIds = segmentation.state
|
const segmentationIds = segmentation.state
|
||||||
.getSegmentations()
|
.getSegmentations()
|
||||||
.map(x => x.segmentationId);
|
.map(x => x.segmentationId);
|
||||||
|
|
@ -1060,6 +1129,10 @@ export default {
|
||||||
} else {
|
} else {
|
||||||
this.downloadDICOMData(generatedSegmentation.dataset, `${group.name}.dcm`);
|
this.downloadDICOMData(generatedSegmentation.dataset, `${group.name}.dcm`);
|
||||||
}
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
downloadDICOMData(bufferOrDataset, filename) {
|
downloadDICOMData(bufferOrDataset, filename) {
|
||||||
let blob;
|
let blob;
|
||||||
|
|
@ -1109,7 +1182,7 @@ export default {
|
||||||
|
|
||||||
const arrayBuffer = image.data.byteArray.buffer;
|
const arrayBuffer = image.data.byteArray.buffer;
|
||||||
await this.loadSegmentation(arrayBuffer, obj.segmentationId);
|
await this.loadSegmentation(arrayBuffer, obj.segmentationId);
|
||||||
this.createSegmentationRepresentation(obj.segmentationId);
|
// this.createSegmentationRepresentation(obj.segmentationId);
|
||||||
},
|
},
|
||||||
async loadSegmentation(arrayBuffer, segmentationId) {
|
async loadSegmentation(arrayBuffer, segmentationId) {
|
||||||
const generateToolState =
|
const generateToolState =
|
||||||
|
|
@ -1292,17 +1365,11 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
createSegmentationRepresentation(segmentationId) {
|
createSegmentationRepresentation(segmentationId) {
|
||||||
this.viewprotIds.forEach(id => {
|
DicomEvent.$emit('createSegmentationRepresentation', segmentationId)
|
||||||
segmentation.addSegmentationRepresentations(id, [
|
|
||||||
{
|
|
||||||
segmentationId,
|
|
||||||
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
|
||||||
},
|
|
||||||
])
|
|
||||||
})
|
|
||||||
this.$emit('setToolsPassive')
|
this.$emit('setToolsPassive')
|
||||||
},
|
},
|
||||||
contentMouseup() {
|
contentMouseup() {
|
||||||
|
try {
|
||||||
// console.log("segment contentMouseup")
|
// console.log("segment contentMouseup")
|
||||||
if (!this.drawing) return false
|
if (!this.drawing) return false
|
||||||
if (this.timeoutId) {
|
if (this.timeoutId) {
|
||||||
|
|
@ -1331,12 +1398,16 @@ export default {
|
||||||
|
|
||||||
}
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
// 获取当前任务分割标记与问题绑定关系
|
// 获取当前任务分割标记与问题绑定关系
|
||||||
async getSegmentBindingList(param = {}) {
|
async getSegmentBindingList(param = {}) {
|
||||||
try {
|
try {
|
||||||
let data = {
|
let data = {
|
||||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
VisitTaskId: this.series.TaskInfo.VisitTaskId,
|
||||||
PageSize: 9999,
|
PageSize: 9999,
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
}
|
}
|
||||||
|
|
@ -1353,7 +1424,7 @@ export default {
|
||||||
async saveSegmentBindingAndAnswer(list) {
|
async saveSegmentBindingAndAnswer(list) {
|
||||||
try {
|
try {
|
||||||
let data = {
|
let data = {
|
||||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
VisitTaskId: this.series.TaskInfo.VisitTaskId,
|
||||||
BindingList: list
|
BindingList: list
|
||||||
}
|
}
|
||||||
let res = await saveSegmentBindingAndAnswer(data)
|
let res = await saveSegmentBindingAndAnswer(data)
|
||||||
|
|
@ -1406,6 +1477,8 @@ export default {
|
||||||
}/${this.series.Id}/${segmentGroup.name}.dcm`
|
}/${this.series.Id}/${segmentGroup.name}.dcm`
|
||||||
const result = await this.OSSclient.put(path, blob)
|
const result = await this.OSSclient.put(path, blob)
|
||||||
segmentGroup.segUrl = this.$getObjectName(result.url)
|
segmentGroup.segUrl = this.$getObjectName(result.url)
|
||||||
|
} else {
|
||||||
|
segmentGroup.segUrl = null
|
||||||
}
|
}
|
||||||
|
|
||||||
this.addOrUpdateSegmentation({ name: segmentGroup.name, id: segmentGroup.segmentationId, url: segmentGroup.segUrl })
|
this.addOrUpdateSegmentation({ name: segmentGroup.name, id: segmentGroup.segmentationId, url: segmentGroup.segUrl })
|
||||||
|
|
@ -1443,7 +1516,6 @@ export default {
|
||||||
list.forEach(item => {
|
list.forEach(item => {
|
||||||
this.createSegmentConfiguration(item.segmentIndex, item.segmentationId);
|
this.createSegmentConfiguration(item.segmentIndex, item.segmentationId);
|
||||||
})
|
})
|
||||||
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
const viewportId = `${this.viewportKey}-${this.activeViewportIndex}`
|
||||||
const viewport = renderingEngine.getViewport(viewportId);
|
const viewport = renderingEngine.getViewport(viewportId);
|
||||||
|
|
@ -1468,7 +1540,7 @@ export default {
|
||||||
|
|
||||||
let bidirectional = bidirectionalData[0]
|
let bidirectional = bidirectionalData[0]
|
||||||
const { segmentIndex } = bidirectional;
|
const { segmentIndex } = bidirectional;
|
||||||
const { majorAxis, minorAxis, maxMajor, maxMinor } = bidirectional;
|
const { majorAxis, minorAxis } = bidirectional;
|
||||||
let item = list.find(i => i.segmentIndex === segmentIndex)
|
let item = list.find(i => i.segmentIndex === segmentIndex)
|
||||||
SegmentBidirectionalTool.hydrate(viewportId, [majorAxis, minorAxis], {
|
SegmentBidirectionalTool.hydrate(viewportId, [majorAxis, minorAxis], {
|
||||||
segmentIndex,
|
segmentIndex,
|
||||||
|
|
@ -1477,7 +1549,7 @@ export default {
|
||||||
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === bidirectional.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === bidirectional.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
if (an) {
|
if (an) {
|
||||||
annotation.locking.setAnnotationLocked(an.annotationUID, true)
|
annotation.locking.setAnnotationLocked(an.annotationUID, true)
|
||||||
annotation.visibility.setAnnotationVisibility(an.annotationUID, item.bidirectionalView)
|
annotation.visibility.setAnnotationVisibility(an.annotationUID, true)
|
||||||
}
|
}
|
||||||
item.bidirectional = bidirectional
|
item.bidirectional = bidirectional
|
||||||
reslove(true)
|
reslove(true)
|
||||||
|
|
@ -1516,13 +1588,13 @@ export default {
|
||||||
answer = segment.stats && segment.stats[imageToolAttribute] ? Number((segment.stats[imageToolAttribute]).value).toFixed(this.digitPlaces) : ''
|
answer = segment.stats && segment.stats[imageToolAttribute] ? Number((segment.stats[imageToolAttribute]).value).toFixed(this.digitPlaces) : ''
|
||||||
}
|
}
|
||||||
let o = {
|
let o = {
|
||||||
Answer: answer,
|
Answer: answer === '-Infinity' || answer === 'NaN' ? null : answer,
|
||||||
QuestionId: item.QuestionId,
|
QuestionId: item.QuestionId,
|
||||||
RowId: item.RowId,
|
RowId: item.RowId,
|
||||||
SegmentId: item.SegmentId,
|
SegmentId: item.SegmentId,
|
||||||
SegmentationId: item.SegmentationId,
|
SegmentationId: item.SegmentationId,
|
||||||
TableQuestionId: item.TableQuestionId,
|
TableQuestionId: item.TableQuestionId,
|
||||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
VisitTaskId: this.series.TaskInfo.VisitTaskId,
|
||||||
}
|
}
|
||||||
bindingList.push(o)
|
bindingList.push(o)
|
||||||
}
|
}
|
||||||
|
|
@ -1540,7 +1612,7 @@ export default {
|
||||||
SubjectId: this.visitInfo.SubjectId,
|
SubjectId: this.visitInfo.SubjectId,
|
||||||
SubjectVisitId: this.visitInfo.VisistId,
|
SubjectVisitId: this.visitInfo.VisistId,
|
||||||
TrialId: this.$route.query.trialId,
|
TrialId: this.$route.query.trialId,
|
||||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
VisitTaskId: this.series.TaskInfo.VisitTaskId,
|
||||||
}
|
}
|
||||||
if (url) data.SegUrl = url;
|
if (url) data.SegUrl = url;
|
||||||
if (id) data.Id = id;
|
if (id) data.Id = id;
|
||||||
|
|
@ -1558,17 +1630,20 @@ export default {
|
||||||
// 获取分割组
|
// 获取分割组
|
||||||
async getSegmentationList(SEGMENT = null) {
|
async getSegmentationList(SEGMENT = null) {
|
||||||
try {
|
try {
|
||||||
|
this.$emit('setToolsPassive')
|
||||||
let data = {
|
let data = {
|
||||||
SeriesId: this.series.Id,
|
SeriesId: this.series.Id,
|
||||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
VisitTaskId: this.series.TaskInfo.VisitTaskId,
|
||||||
PageSize: 9999,
|
PageSize: 9999,
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
}
|
}
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
let res = await getSegmentationList(data);
|
let res = await getSegmentationList(data);
|
||||||
this.loading = false;
|
// this.loading = false;
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
this.segmentList = []
|
this.segmentList = []
|
||||||
|
this.segmentationId = null;
|
||||||
|
this.segmentIndex = null;
|
||||||
let list = res.Result.CurrentPageData;
|
let list = res.Result.CurrentPageData;
|
||||||
for (let i = 0; i < list.length; i++) {
|
for (let i = 0; i < list.length; i++) {
|
||||||
let item = list[i]
|
let item = list[i]
|
||||||
|
|
@ -1583,12 +1658,6 @@ export default {
|
||||||
segments: []
|
segments: []
|
||||||
}
|
}
|
||||||
this.segmentList.push(obj)
|
this.segmentList.push(obj)
|
||||||
if (item.SEGUrl) {
|
|
||||||
await this.readSegmentation(obj)
|
|
||||||
} else {
|
|
||||||
await this.createSegmentation(obj.segmentationId)
|
|
||||||
this.createSegmentationRepresentation(obj.segmentationId)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!this.segmentationId) {
|
if (!this.segmentationId) {
|
||||||
this.segmentationId = obj.segmentationId
|
this.segmentationId = obj.segmentationId
|
||||||
|
|
@ -1607,48 +1676,20 @@ export default {
|
||||||
bidirectional: SegmentJson.bidirectional,
|
bidirectional: SegmentJson.bidirectional,
|
||||||
bidirectionalView: true,
|
bidirectionalView: true,
|
||||||
view: true,
|
view: true,
|
||||||
lock: item.locked,
|
lock: true,
|
||||||
id: s.Id
|
id: s.Id
|
||||||
}
|
}
|
||||||
obj.segments.push(o)
|
obj.segments.push(o)
|
||||||
this.selectSegment(o, false)
|
|
||||||
this.changeColor(s.ColorRgb, o)
|
|
||||||
this.lockSegment(o, true)
|
|
||||||
}
|
}
|
||||||
if (!this.segmentIndex) {
|
if (!this.segmentIndex) {
|
||||||
this.segmentIndex = s.SegmentNumber
|
this.segmentIndex = s.SegmentNumber
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
this.$nextTick(() => {
|
|
||||||
if (SEGMENT) {
|
|
||||||
// console.log(SEGMENT, 'SEGMENT')
|
|
||||||
return this.getBidirectional(obj.segments, SEGMENT)
|
|
||||||
}
|
|
||||||
this.getBidirectional(obj.segments, null, false)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
if (this.segmentationId && this.segmentIndex && this.segmentList && this.segmentList.length > 0) {
|
|
||||||
let o = this.segmentList.find(item => item.segmentationId === this.segmentationId)
|
|
||||||
if (o) {
|
|
||||||
let s = o.segments.find(item => item.segmentIndex === this.segmentIndex)
|
|
||||||
this.selectSegmentGroup(s)
|
|
||||||
} else {
|
|
||||||
this.segmentationId = this.segmentList[0].segmentationId
|
|
||||||
this.segmentIndex = this.segmentationId ? this.segmentList[0].segments[0].segmentIndex : null
|
|
||||||
if (this.segmentationId && this.segmentIndex) {
|
|
||||||
this.selectSegmentGroup(this.segmentList[0].segments[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
// console.log(segment, 'segment')
|
|
||||||
|
|
||||||
// this.selectSegment(segment)
|
|
||||||
}
|
}
|
||||||
this.isloaded = false
|
this.isloaded = false
|
||||||
this.readingSegmentByConfig()
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.loading = false
|
// this.loading = false
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -1674,7 +1715,7 @@ export default {
|
||||||
SegmentName: name,
|
SegmentName: name,
|
||||||
SegmentNumber: segmentIndex,
|
SegmentNumber: segmentIndex,
|
||||||
SegmentationId: segmentationId,
|
SegmentationId: segmentationId,
|
||||||
VisitTaskId: this.visitInfo.VisitTaskId,
|
VisitTaskId: this.series.TaskInfo.VisitTaskId,
|
||||||
SegmentJson: segmentJson
|
SegmentJson: segmentJson
|
||||||
}
|
}
|
||||||
if (id) data.Id = id
|
if (id) data.Id = id
|
||||||
|
|
@ -1697,14 +1738,14 @@ export default {
|
||||||
PageSize: 9999,
|
PageSize: 9999,
|
||||||
PageIndex: 1,
|
PageIndex: 1,
|
||||||
}
|
}
|
||||||
this.loading = true;
|
// this.loading = true;
|
||||||
let res = await getSegmentList(data)
|
let res = await getSegmentList(data)
|
||||||
this.loading = false;
|
// this.loading = false;
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
return res.Result.CurrentPageData
|
return res.Result.CurrentPageData
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.loading = false
|
// this.loading = false
|
||||||
console.log(err)
|
console.log(err)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="ps">
|
<div class="ps">
|
||||||
<el-collapse v-model="activeNames">
|
<el-collapse v-model="activeNames">
|
||||||
<el-collapse-item v-for="(study, index) in studyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
<template v-for="(study, index) in studyList">
|
||||||
|
<el-collapse-item :key="`${study.StudyId}`" :name="`${study.StudyId}`" v-if="!study.IsCriticalSequence">
|
||||||
<template slot="title">
|
<template slot="title">
|
||||||
<div v-if="!study.IsCriticalSequence" class="dicom-desc">
|
<div v-if="readingTool !== 3 || !study.IsCriticalSequence" class="dicom-desc">
|
||||||
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
||||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
||||||
|
|
@ -53,7 +54,8 @@
|
||||||
style="position: absolute;right: 0;top: 0;">
|
style="position: absolute;right: 0;top: 0;">
|
||||||
<el-popover placement="right" trigger="hover" popper-class="instance_frame_wrapper">
|
<el-popover placement="right" trigger="hover" popper-class="instance_frame_wrapper">
|
||||||
<div class="frame_list">
|
<div class="frame_list">
|
||||||
<div v-for="(instance, idx) in series.InstanceInfoList" :key="instance.Id" class="frame_content"
|
<div v-for="(instance, idx) in series.InstanceInfoList" :key="instance.Id"
|
||||||
|
class="frame_content"
|
||||||
:style="{ 'margin-bottom': idx < series.InstanceInfoList.length - 1 ? '5px' : '0px' }"
|
:style="{ 'margin-bottom': idx < series.InstanceInfoList.length - 1 ? '5px' : '0px' }"
|
||||||
@click.stop="showMultiFrames(index, series, i, instance)">
|
@click.stop="showMultiFrames(index, series, i, instance)">
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -99,6 +101,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</el-collapse-item>
|
</el-collapse-item>
|
||||||
|
</template>
|
||||||
|
|
||||||
</el-collapse>
|
</el-collapse>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -119,6 +123,10 @@ export default {
|
||||||
default() {
|
default() {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
readingTool: {
|
||||||
|
type: Number,
|
||||||
|
default: 2
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
|
@ -248,6 +256,7 @@ export default {
|
||||||
background-color: #607d8b !important;
|
background-color: #607d8b !important;
|
||||||
border: 1px solid #607d8b !important;
|
border: 1px solid #607d8b !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-progress__text {
|
::v-deep .el-progress__text {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
|
|
@ -299,6 +308,7 @@ export default {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-collapse {
|
::v-deep .el-collapse {
|
||||||
border: none;
|
border: none;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<template>
|
||||||
|
<div class="SurfaceViewport" ref="SurfaceViewport" v-show="visible" id="SurfaceViewport"></div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getRenderingEngine,
|
||||||
|
CONSTANTS,
|
||||||
|
setVolumesForViewports,
|
||||||
|
eventTarget,
|
||||||
|
Enums,
|
||||||
|
utilities,
|
||||||
|
} from '@cornerstonejs/core'
|
||||||
|
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||||
|
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||||
|
const {
|
||||||
|
Enums: csToolsEnums,
|
||||||
|
segmentation,
|
||||||
|
TrackballRotateTool,
|
||||||
|
ToolGroupManager
|
||||||
|
} = cornerstoneTools
|
||||||
|
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||||
|
export default {
|
||||||
|
name: "SurfaceViewport",
|
||||||
|
props: {
|
||||||
|
renderingEngineId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
viewportId: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
visitInfo: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
visible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
volumeId: null,
|
||||||
|
info: null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
eventTarget.addEventListener(Enums.Events.WEB_WORKER_PROGRESS, (evt) => {
|
||||||
|
const { progress } = evt.detail;
|
||||||
|
console.log(progress, 'progress')
|
||||||
|
});
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async setSeriesInfo(obj) {
|
||||||
|
try {
|
||||||
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
|
let { volumeId } = obj
|
||||||
|
this.info = obj
|
||||||
|
this.volumeId = volumeId
|
||||||
|
await setVolumesForViewports(
|
||||||
|
renderingEngine,
|
||||||
|
[{ volumeId, callback: setCtTransferFunctionForVolumeActor }],
|
||||||
|
[this.viewportId]
|
||||||
|
);
|
||||||
|
const volumeActor = viewport.getDefaultActor()
|
||||||
|
.actor;
|
||||||
|
utilities.applyPreset(
|
||||||
|
volumeActor,
|
||||||
|
CONSTANTS.VIEWPORT_PRESETS.find((preset) => preset.name === 'CT-Bone')
|
||||||
|
);
|
||||||
|
volumeActor.setVisibility(false);
|
||||||
|
viewport.render();
|
||||||
|
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
async setSurface() {
|
||||||
|
let { segmentationId, segmentations } = this.info
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(this.viewportId)
|
||||||
|
toolGroup.setToolActive(TrackballRotateTool.toolName, {
|
||||||
|
bindings: [
|
||||||
|
{
|
||||||
|
mouseButton: MouseBindings.Primary,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
let s = segmentation.getActiveSegmentation(this.viewportId)
|
||||||
|
console.log(s)
|
||||||
|
if (s) {
|
||||||
|
await segmentation.removeSegmentationRepresentation(this.viewportId, {
|
||||||
|
segmentationId: s.segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Surface,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
await segmentation.addSegmentationRepresentations(this.viewportId, [
|
||||||
|
{
|
||||||
|
segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Contour,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
console.log("loading...")
|
||||||
|
this.$nextTick(async () => {
|
||||||
|
await segmentation.addSegmentationRepresentations(this.viewportId, [
|
||||||
|
{
|
||||||
|
segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Surface,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
segmentations.segments.forEach(item => {
|
||||||
|
segmentation.config.color.setSegmentIndexColor(this.viewportId, item.segmentationId, item.segmentIndex, this.hex2Rgb(item.color))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
hex2Rgb(hexValue, alpha = 1) {
|
||||||
|
const rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||||
|
const hex = hexValue.replace(rgx, (m, r, g, b) => r + r + g + g + b + b);
|
||||||
|
const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
if (!rgb) {
|
||||||
|
return hexValue;
|
||||||
|
}
|
||||||
|
const r = parseInt(rgb[1], 16),
|
||||||
|
g = parseInt(rgb[2], 16),
|
||||||
|
b = parseInt(rgb[3], 16);
|
||||||
|
return [r, g, b, alpha * 255];
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
#SurfaceViewport {
|
||||||
|
width: 450px;
|
||||||
|
height: 300px;
|
||||||
|
position: fixed;
|
||||||
|
top: 100px;
|
||||||
|
z-index: 9999;
|
||||||
|
left: 100px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -14,6 +14,25 @@
|
||||||
<div v-if="imageInfo.total">Image: #{{ `${series.SliceIndex + 1}/${imageInfo.total}` }}</div>
|
<div v-if="imageInfo.total">Image: #{{ `${series.SliceIndex + 1}/${imageInfo.total}` }}</div>
|
||||||
<div>{{ series.Modality }}</div>
|
<div>{{ series.Modality }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div v-if="series && taskInfo && taskInfo.IsReadingTaskViewInOrder === 1" class="top-center-tool">
|
||||||
|
<div class="toggle-visit-container">
|
||||||
|
<div class="arrw_icon"
|
||||||
|
:style="{ cursor: series.TaskInfo && series.TaskInfo.VisitTaskNum !== 0 ? 'pointer' : 'not-allowed', color: series.TaskInfo && series.TaskInfo.VisitTaskNum !== 0 ? '#fff' : '#6b6b6b' }"
|
||||||
|
@click.stop.prevent="toggleTask($event, series.TaskInfo.VisitTaskNum, -1)"
|
||||||
|
@dblclick.stop="preventDefault($event)">
|
||||||
|
<i class="el-icon-caret-left" />
|
||||||
|
</div>
|
||||||
|
<div class="arrow_text">
|
||||||
|
{{ series.TaskInfo ? series.TaskInfo.TaskBlindName : '' }}
|
||||||
|
</div>
|
||||||
|
<div class="arrw_icon"
|
||||||
|
:style="{ cursor: series.TaskInfo && series.TaskInfo.VisitTaskNum < taskInfo.VisitNum ? 'pointer' : 'not-allowed', color: series.TaskInfo && series.TaskInfo.VisitTaskNum < taskInfo.VisitNum ? '#fff' : '#6b6b6b' }"
|
||||||
|
@click.stop.prevent="toggleTask($event, series.TaskInfo.VisitTaskNum, 1)"
|
||||||
|
@dblclick.stop="preventDefault($event)">
|
||||||
|
<i class="el-icon-caret-right" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div v-if="series" class="right-top-text">
|
<div v-if="series" class="right-top-text">
|
||||||
<div>{{ series.Description }}</div>
|
<div>{{ series.Description }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -78,9 +97,24 @@ import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||||
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
|
import { createImageIdsAndCacheMetaData } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/createImageIdsAndCacheMetaData'
|
||||||
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
import setCtTransferFunctionForVolumeActor from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||||
import { setCtMappingRange } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
import { setCtMappingRange } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setCtTransferFunctionForVolumeActor'
|
||||||
import { setPetColorMapTransferFunctionForVolumeActor } from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/setPetColorMapTransferFunctionForVolumeActor'
|
|
||||||
import { vec3, mat4 } from 'gl-matrix'
|
import { vec3, mat4 } from 'gl-matrix'
|
||||||
|
import {
|
||||||
|
setPetTransferFunctionForVolumeActor
|
||||||
|
} from './helpers/index.js'
|
||||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||||
|
import {
|
||||||
|
renderSegmentation,
|
||||||
|
readingSegmentByConfig,
|
||||||
|
selectSegmentation,
|
||||||
|
selectSegment,
|
||||||
|
createSegmentationRepresentation,
|
||||||
|
viewSegmentation,
|
||||||
|
viewSegment,
|
||||||
|
jumpBidirectional,
|
||||||
|
viewBidirectional,
|
||||||
|
changeColor,
|
||||||
|
resetViewport
|
||||||
|
} from "./helpers/segmentations"
|
||||||
export default {
|
export default {
|
||||||
name: 'MPRViewport',
|
name: 'MPRViewport',
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -96,6 +130,36 @@ export default {
|
||||||
type: Number,
|
type: Number,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
histogramVisible: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
actionConfiguration: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
SegmentConfig: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
curSegSeries: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
segmentIndex: {
|
||||||
|
type: Number,
|
||||||
|
default: 0
|
||||||
|
},
|
||||||
|
segmentationId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
@ -139,6 +203,7 @@ export default {
|
||||||
rotateAngle: 0,
|
rotateAngle: 0,
|
||||||
rotateBarLeft: 0,
|
rotateBarLeft: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
toggleClipPlayTimer: null
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
|
@ -148,6 +213,39 @@ export default {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.initViewport()
|
this.initViewport()
|
||||||
})
|
})
|
||||||
|
DicomEvent.$on('createSegmentationRepresentation', (segmentationId) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
createSegmentationRepresentation(this.viewportId, segmentationId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('viewSegmentation', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
viewSegmentation(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('viewSegment', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
viewSegment(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('jumpBidirectional', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
jumpBidirectional(obj, this.viewportId, this.volumeId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('viewBidirectional', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
viewBidirectional(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('changeColor', (obj) => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
changeColor(obj, this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('resetViewport', () => {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.TaskInfo.VisitTaskId !== this.series.TaskInfo.VisitTaskId) return false
|
||||||
|
resetViewport(this.viewportId)
|
||||||
|
})
|
||||||
|
DicomEvent.$on('renderSegmentation', async (viewportId) => {
|
||||||
|
// if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
|
if (this.viewportId !== viewportId) return false
|
||||||
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, null, this.actionConfiguration)
|
||||||
|
})
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
MPRInfo: {
|
MPRInfo: {
|
||||||
|
|
@ -166,6 +264,25 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true
|
deep: true
|
||||||
|
},
|
||||||
|
SegmentConfig: {
|
||||||
|
handler() {
|
||||||
|
if (!this.segmentationId) return false
|
||||||
|
if (!this.series.TaskInfo) return false
|
||||||
|
readingSegmentByConfig(this.series, this.series.TaskInfo, this.viewportId, this.segmentationId, this.SegmentConfig)
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
segmentIndex() {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
|
if (this.segmentIndex <= 0) return false
|
||||||
|
selectSegment(this.viewportId, this.segmentationId, this.segmentIndex)
|
||||||
|
},
|
||||||
|
segmentationId() {
|
||||||
|
if (this.curSegSeries.Id !== this.series.Id || this.curSegSeries.VisitTaskId !== this.series.VisitTaskId) return false
|
||||||
|
if (!this.segmentationId) return false
|
||||||
|
selectSegmentation(this.viewportId, this.segmentationId)
|
||||||
|
readingSegmentByConfig(this.series, this.series.TaskInfo, this.viewportId, this.segmentationId, this.SegmentConfig)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -183,6 +300,7 @@ export default {
|
||||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||||
this.element.addEventListener('CORNERSTONE_IMAGE_RENDERED', this.imageRendered)
|
this.element.addEventListener('CORNERSTONE_IMAGE_RENDERED', this.imageRendered)
|
||||||
this.element.addEventListener('wheel', (e) => {
|
this.element.addEventListener('wheel', (e) => {
|
||||||
|
// if (this.histogramVisible) return false
|
||||||
console.log('CORNERSTONE_STACK_VIEWPORT_SCROLL')
|
console.log('CORNERSTONE_STACK_VIEWPORT_SCROLL')
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
|
|
@ -266,6 +384,7 @@ export default {
|
||||||
},
|
},
|
||||||
stackNewImage(e) {
|
stackNewImage(e) {
|
||||||
const { detail } = e
|
const { detail } = e
|
||||||
|
|
||||||
this.series.SliceIndex = detail.imageIndex
|
this.series.SliceIndex = detail.imageIndex
|
||||||
this.sliderInfo.height = detail.imageIndex * 100 / detail.numberOfSlices
|
this.sliderInfo.height = detail.imageIndex * 100 / detail.numberOfSlices
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
|
|
@ -286,13 +405,14 @@ export default {
|
||||||
let spacing = volume ? volume.spacing : []
|
let spacing = volume ? volume.spacing : []
|
||||||
this.imageInfo.sliceThickness = type === 'AXIAL' ? spacing[2] : spacing[0]
|
this.imageInfo.sliceThickness = type === 'AXIAL' ? spacing[2] : spacing[0]
|
||||||
this.getOrientationMarker()
|
this.getOrientationMarker()
|
||||||
if (this.series && this.series.Id) {
|
// if (this.series && this.series.Id) {
|
||||||
let annotations = cornerstoneTools.annotation.state.getAllAnnotations().filter(item => item.metadata.toolName !== 'ScaleOverlay' && item.metadata.volumeId !== this.volumeId && !item.metadata.segmentationId && item.seriesId !== this.series.Id)
|
// let annotations = cornerstoneTools.annotation.state.getAllAnnotations().filter(item => item.metadata.toolName !== 'ScaleOverlay' && item.metadata.volumeId !== this.volumeId && !item.metadata.segmentationId && item.seriesId !== this.series.Id)
|
||||||
annotations.forEach(item => {
|
// annotations.forEach(item => {
|
||||||
cornerstoneTools.annotation.state.removeAnnotation(item.annotationUID)
|
// cornerstoneTools.annotation.state.removeAnnotation(item.annotationUID)
|
||||||
})
|
// })
|
||||||
}
|
// }
|
||||||
this.$emit('renderAnnotations', this.series)
|
this.$emit('renderAnnotations', this.series)
|
||||||
|
this.$emit("resetHistogram")
|
||||||
let properties = viewport.getProperties()
|
let properties = viewport.getProperties()
|
||||||
if (this.isFusion) {
|
if (this.isFusion) {
|
||||||
properties = viewport.getProperties(this.ptVolumeId)
|
properties = viewport.getProperties(this.ptVolumeId)
|
||||||
|
|
@ -418,11 +538,20 @@ export default {
|
||||||
this.playClipState = isPlay
|
this.playClipState = isPlay
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
|
|
||||||
if (isPlay) {
|
if (isPlay) {
|
||||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
|
this.toggleClipPlayTimer = setInterval(() => {
|
||||||
|
let index = this.series.SliceIndex + 1;
|
||||||
|
if (index > this.imageInfo.total - 1) index = 0
|
||||||
|
csUtils.jumpToSlice(viewport.element, { imageIndex: index });
|
||||||
|
|
||||||
|
}, framesPerSecond)
|
||||||
|
// cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond, loop: true })
|
||||||
} else {
|
} else {
|
||||||
cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
if (this.toggleClipPlayTimer) {
|
||||||
|
clearInterval(this.toggleClipPlayTimer)
|
||||||
|
this.toggleClipPlayTimer = null
|
||||||
|
}
|
||||||
|
// cornerstoneTools.utilities.cine.stopClip(viewport.element)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
scrollPage(type) {
|
scrollPage(type) {
|
||||||
|
|
@ -520,7 +649,6 @@ export default {
|
||||||
if (this.series && data.Id === this.series.Id && data.Description === this.series.Description && !isLocate && !data.isLocation) {
|
if (this.series && data.Id === this.series.Id && data.Description === this.series.Description && !isLocate && !data.isLocation) {
|
||||||
data.SliceIndex = this.series.SliceIndex
|
data.SliceIndex = this.series.SliceIndex
|
||||||
}
|
}
|
||||||
// console.log(data)
|
|
||||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||||
if (isLocate) return csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex });
|
if (isLocate) return csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex });
|
||||||
|
|
@ -532,7 +660,8 @@ export default {
|
||||||
.setVolumes([{
|
.setVolumes([{
|
||||||
volumeId: this.volumeId, callback: (r) => {
|
volumeId: this.volumeId, callback: (r) => {
|
||||||
if (this.series.Modality === 'PT' || this.series.Modality === 'NM') {
|
if (this.series.Modality === 'PT' || this.series.Modality === 'NM') {
|
||||||
setPetColorMapTransferFunctionForVolumeActor(r, true)
|
setPetTransferFunctionForVolumeActor(r)
|
||||||
|
// viewport.setProperties({ voiRange: { upper: 5, lower: 0 } })
|
||||||
} else {
|
} else {
|
||||||
const voi = metaData.get('voiLutModule', res.volume._imageIds[Math.ceil((res.volume._imageIds.length - 1) / 2)])
|
const voi = metaData.get('voiLutModule', res.volume._imageIds[Math.ceil((res.volume._imageIds.length - 1) / 2)])
|
||||||
setCtMappingRange(voi.windowWidth[0], voi.windowCenter[0])
|
setCtMappingRange(voi.windowWidth[0], voi.windowCenter[0])
|
||||||
|
|
@ -541,19 +670,28 @@ export default {
|
||||||
console.log("渲染成功")
|
console.log("渲染成功")
|
||||||
}
|
}
|
||||||
}]).then(r => {
|
}]).then(r => {
|
||||||
if (data.segment) {
|
|
||||||
return DicomEvent.$emit("isloaded", { segment: data.segment, isChange: data.isChange })
|
|
||||||
}
|
|
||||||
if (data.isLocation) {
|
if (data.isLocation) {
|
||||||
setTimeout(() => { csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex }); })
|
setTimeout(() => { csUtils.jumpToSlice(viewport.element, { imageIndex: data.SliceIndex }); })
|
||||||
}
|
}
|
||||||
DicomEvent.$emit("isloaded", { isChange: data.isChange })
|
|
||||||
})
|
})
|
||||||
|
res.volume.dimensionGroupNumber = 2;
|
||||||
viewport.render()
|
viewport.render()
|
||||||
|
if (this.series.Modality === 'PT' || this.series.Modality === 'NM') {
|
||||||
|
setTimeout(() => {
|
||||||
|
viewport.resetCamera({ resetPan: true, resetZoom: true, resetToCenter: true })
|
||||||
|
viewport.resetProperties()
|
||||||
|
viewport.setProperties({ voiRange: { upper: 5, lower: 0 } })
|
||||||
|
viewport.render()
|
||||||
|
renderingEngine.render()
|
||||||
|
}, 100)
|
||||||
|
}
|
||||||
|
await renderSegmentation(this.series, this.series.TaskInfo, this.viewportId, this.SegmentConfig, this.renderingEngineId, data.segment, this.actionConfiguration)
|
||||||
|
DicomEvent.$emit('SegmentationLoading', this.viewportId)
|
||||||
|
if (this.series.hasOwnProperty('curIndex')) return this.setFullScreen(this.series.curIndex)
|
||||||
|
this.setFullScreen(Math.ceil((res.volume._imageIds.length - 1) / 2) - 1)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e)
|
console.log(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
cornerstoneToolsMouseMove(e) {
|
cornerstoneToolsMouseMove(e) {
|
||||||
const { currentPoints } = e.detail
|
const { currentPoints } = e.detail
|
||||||
|
|
@ -723,6 +861,12 @@ export default {
|
||||||
return `NS: ${this.$store.state.trials.downloadTip}`
|
return `NS: ${this.$store.state.trials.downloadTip}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
destroyed() {
|
||||||
|
if (this.toggleClipPlayTimer) {
|
||||||
|
clearInterval(this.toggleClipPlayTimer)
|
||||||
|
this.toggleClipPlayTimer = null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
|
||||||
|
|
@ -1357,6 +1357,7 @@ export default {
|
||||||
await this.getQuestionCalculateRelation()
|
await this.getQuestionCalculateRelation()
|
||||||
await this.getQuestions(true)
|
await this.getQuestions(true)
|
||||||
this.$emit('resetAnnotations', this.visitTaskId)
|
this.$emit('resetAnnotations', this.visitTaskId)
|
||||||
|
this.initSegmentBinding()
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.rerender = true
|
this.rerender = true
|
||||||
})
|
})
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,436 @@
|
||||||
|
import * as cornerstoneTools from '@cornerstonejs/tools';
|
||||||
|
import * as cornerstone from "@cornerstonejs/core";
|
||||||
|
import dcmjs from '@/utils/dcmUpload/dcmjs'
|
||||||
|
import * as cornerstoneAdapters from "@cornerstonejs/adapters";
|
||||||
|
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'
|
||||||
|
import * as polySeg from '@cornerstonejs/polymorphic-segmentation'
|
||||||
|
cornerstoneTools.init({ addons: { polySeg } })
|
||||||
|
import { getSegmentationList, getSegmentList } from '@/api/reading'
|
||||||
|
import Vue from 'vue'
|
||||||
|
const {
|
||||||
|
ToolGroupManager,
|
||||||
|
Enums: csToolsEnums,
|
||||||
|
segmentation,
|
||||||
|
annotation,
|
||||||
|
LabelMapEditWithContourTool,
|
||||||
|
SegmentBidirectionalTool,
|
||||||
|
CrosshairsTool,
|
||||||
|
utilities: CStUtils,
|
||||||
|
} = cornerstoneTools;
|
||||||
|
const { MouseBindings, Events: toolsEvents } = csToolsEnums
|
||||||
|
const { segmentation: segmentationUtils } = CStUtils;
|
||||||
|
const { cache, getRenderingEngine, imageLoader, eventTarget, metaData, utilities: csUtils, volumeLoader } = cornerstone;
|
||||||
|
const { Cornerstone3D } = cornerstoneAdapters.adaptersSEG;
|
||||||
|
let viewportInfo = {}
|
||||||
|
let renderingEngineId = null
|
||||||
|
async function createSegmentation(toolGroupId, volumeId, segmentationId) {
|
||||||
|
const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) || ToolGroupManager.getToolGroup('share-viewport-volume')
|
||||||
|
toolGroup.setToolActive(
|
||||||
|
LabelMapEditWithContourTool.toolName,
|
||||||
|
);
|
||||||
|
if (!cache.getVolume(segmentationId)) {
|
||||||
|
await volumeLoader.createAndCacheDerivedLabelmapVolume(
|
||||||
|
volumeId,
|
||||||
|
{
|
||||||
|
volumeId: segmentationId
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
if (!segmentation.state.getSegmentation(segmentationId)) {
|
||||||
|
segmentation.addSegmentations([
|
||||||
|
{
|
||||||
|
segmentationId,
|
||||||
|
representation: {
|
||||||
|
type: cornerstoneTools.Enums.SegmentationRepresentations
|
||||||
|
.Labelmap,
|
||||||
|
data: {
|
||||||
|
volumeId: segmentationId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async function createSegmentationRepresentation(viewportId, segmentationId) {
|
||||||
|
segmentation.addSegmentationRepresentations(viewportId, [
|
||||||
|
{
|
||||||
|
segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
||||||
|
},
|
||||||
|
])
|
||||||
|
}
|
||||||
|
async function readSegmentation(obj, series, segmentationId, isFile = false) {
|
||||||
|
let imageId = null
|
||||||
|
if (isFile) {
|
||||||
|
imageId = cornerstoneDICOMImageLoader.wadouri.fileManager.add(obj);
|
||||||
|
} else {
|
||||||
|
const imageIdObj = await cornerstoneDICOMImageLoader.wadouri.loadImage(`wadouri:${Vue.prototype.OSSclientConfig.basePath}${obj}`).promise
|
||||||
|
imageId = imageIdObj.imageId
|
||||||
|
}
|
||||||
|
const image = await imageLoader.loadAndCacheImage(imageId);
|
||||||
|
|
||||||
|
if (!image) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = metaData.get("instance", imageId);
|
||||||
|
|
||||||
|
if (instance.Modality !== "SEG") {
|
||||||
|
console.error("This is not segmentation: " + file.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const arrayBuffer = image.data.byteArray.buffer;
|
||||||
|
await loadSegmentation(arrayBuffer, series, segmentationId);
|
||||||
|
}
|
||||||
|
async function loadSegmentation(arrayBuffer, series, segmentationId) {
|
||||||
|
const generateToolState =
|
||||||
|
await Cornerstone3D.Segmentation.generateToolState(
|
||||||
|
series.ImageIds,
|
||||||
|
arrayBuffer,
|
||||||
|
metaData,
|
||||||
|
);
|
||||||
|
if (generateToolState.labelmapBufferArray.length !== 1) {
|
||||||
|
alert(
|
||||||
|
"Overlapping segments in your segmentation are not supported yet. You can turn on the skipOverlapping option but it will override the overlapping segments."
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// await createSegmentation(segmentationId);
|
||||||
|
let arr = []
|
||||||
|
generateToolState.segMetadata.data.forEach(item => {
|
||||||
|
if (item) {
|
||||||
|
let Target = JSON.parse(JSON.stringify(item))
|
||||||
|
arr.push(Target)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
let mapping = {}
|
||||||
|
|
||||||
|
arr.forEach((item, index) => {
|
||||||
|
mapping[index + 1] = Number(item.SegmentNumber)
|
||||||
|
})
|
||||||
|
const megmentGroup =
|
||||||
|
segmentation.state.getSegmentation(segmentationId);
|
||||||
|
const { imageIds } = megmentGroup.representationData.Labelmap;
|
||||||
|
const derivedSegmentationImages = imageIds.map(imageId =>
|
||||||
|
cache.getImage(imageId)
|
||||||
|
);
|
||||||
|
|
||||||
|
const volumeScalarData = new Uint8Array(
|
||||||
|
generateToolState.labelmapBufferArray[0]
|
||||||
|
);
|
||||||
|
const remappedData = new Uint8Array(volumeScalarData.length);
|
||||||
|
for (let i = 0; i < volumeScalarData.length; i++) {
|
||||||
|
const value = volumeScalarData[i];
|
||||||
|
remappedData[i] = value === 0 ? 0 : (mapping[value] ? mapping[value] : value);
|
||||||
|
}
|
||||||
|
for (let i = 0; i < derivedSegmentationImages.length; i++) {
|
||||||
|
const voxelManager = derivedSegmentationImages[i].voxelManager;
|
||||||
|
const scalarData = voxelManager.getScalarData();
|
||||||
|
scalarData.set(
|
||||||
|
remappedData.slice(
|
||||||
|
i * scalarData.length,
|
||||||
|
(i + 1) * scalarData.length
|
||||||
|
)
|
||||||
|
);
|
||||||
|
voxelManager.setScalarData(scalarData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function hex2Rgb(hexValue, alpha = 1) {
|
||||||
|
const rgx = /^#?([a-f\d])([a-f\d])([a-f\d])$/i;
|
||||||
|
const hex = hexValue.replace(rgx, (m, r, g, b) => r + r + g + g + b + b);
|
||||||
|
const rgb = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
|
||||||
|
if (!rgb) {
|
||||||
|
return hexValue;
|
||||||
|
}
|
||||||
|
const r = parseInt(rgb[1], 16),
|
||||||
|
g = parseInt(rgb[2], 16),
|
||||||
|
b = parseInt(rgb[3], 16);
|
||||||
|
return [r, g, b, alpha * 255];
|
||||||
|
}
|
||||||
|
function removeSegmentFromViewport(viewportId) {
|
||||||
|
return new Promise(resolve => {
|
||||||
|
if (viewportInfo[viewportId] && viewportInfo[viewportId].length > 0) {
|
||||||
|
viewportInfo[viewportId].forEach(async segmentationId => {
|
||||||
|
segmentation.removeSegmentation(segmentationId)
|
||||||
|
segmentation.state.removeSegmentation(segmentationId)
|
||||||
|
let annotations = annotation.state.getAllAnnotations().filter(item => item.metadata.segmentationId && segmentationId === item.metadata.segmentationId && item.metadata.toolName === "SegmentBidirectional");
|
||||||
|
annotations.forEach(item => {
|
||||||
|
annotation.state.removeAnnotation(item.annotationUID)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
resetViewport(viewportId)
|
||||||
|
}
|
||||||
|
viewportInfo[viewportId] = []
|
||||||
|
resolve(true)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
function createSegmentConfiguration(segmentIndex, segmentationId, viewportId, actionConfiguration, otherSegments) {
|
||||||
|
const containedSegmentIndices = otherSegments
|
||||||
|
? { has: (segmentIndex) => otherSegments.indexOf(segmentIndex) !== -1 }
|
||||||
|
: undefined;
|
||||||
|
const colorConfig = segmentation.config.color.getSegmentIndexColor(
|
||||||
|
viewportId,
|
||||||
|
segmentationId,
|
||||||
|
segmentIndex
|
||||||
|
);
|
||||||
|
// Allow null style to skip style set
|
||||||
|
let color, activeColor;
|
||||||
|
if (colorConfig?.length) {
|
||||||
|
color = `rgb(${colorConfig.join(',')})`;
|
||||||
|
activeColor = color;
|
||||||
|
}
|
||||||
|
const style = {
|
||||||
|
color,
|
||||||
|
colorHighlightedActive: activeColor,
|
||||||
|
colorActive: activeColor,
|
||||||
|
textBoxColor: color,
|
||||||
|
textBoxColorActive: activeColor,
|
||||||
|
textBoxColorHighlightedActive: activeColor,
|
||||||
|
};
|
||||||
|
const label = otherSegments
|
||||||
|
? `Combined ${segmentIndex} with ${otherSegments.join(', ')}`
|
||||||
|
: `Segment ${segmentIndex}`;
|
||||||
|
|
||||||
|
actionConfiguration.contourBidirectional.data.segmentData.set(segmentIndex, {
|
||||||
|
containedSegmentIndices,
|
||||||
|
label,
|
||||||
|
style,
|
||||||
|
});
|
||||||
|
actionConfiguration.contourBidirectional.data.segmentationId = segmentationId
|
||||||
|
actionConfiguration.contourBidirectional.data.segmentIndex = segmentIndex
|
||||||
|
}
|
||||||
|
async function readingSegmentByConfig(series, visitInfo, viewportId, segmentationId, SegmentConfig) {
|
||||||
|
let data = {
|
||||||
|
SeriesId: series.Id,
|
||||||
|
VisitTaskId: visitInfo.VisitTaskId,
|
||||||
|
PageSize: 9999,
|
||||||
|
PageIndex: 1,
|
||||||
|
}
|
||||||
|
let res = await getSegmentationList(data);
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
let list = res.Result.CurrentPageData;
|
||||||
|
changeInactiveSegmentShow(list, viewportId, segmentationId, SegmentConfig)
|
||||||
|
}
|
||||||
|
segmentation.config.style.setStyle(
|
||||||
|
{
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
renderFill: SegmentConfig.renderFill,
|
||||||
|
renderOutline: SegmentConfig.renderOutline,
|
||||||
|
outlineWidth: Number(SegmentConfig.outlineWidth),
|
||||||
|
fillAlpha: Number(SegmentConfig.fillAlpha),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
function selectSegmentation(viewportId, segmentationId) {
|
||||||
|
segmentation.activeSegmentation.setActiveSegmentation(viewportId, segmentationId)
|
||||||
|
}
|
||||||
|
function selectSegment(viewportId, segmentationId, segmentIndex) {
|
||||||
|
selectSegmentation(viewportId, segmentationId)
|
||||||
|
segmentation.segmentIndex.setActiveSegmentIndex(segmentationId, segmentIndex);
|
||||||
|
}
|
||||||
|
async function changeInactiveSegmentShow(list, viewportId, segmentationId, SegmentConfig) {
|
||||||
|
let segmentList = list
|
||||||
|
segmentList.forEach(segment => {
|
||||||
|
segmentation.config.visibility.setSegmentationRepresentationVisibility(
|
||||||
|
viewportId,
|
||||||
|
{
|
||||||
|
segmentationId: segment.Id,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
||||||
|
},
|
||||||
|
SegmentConfig.InactiveSegmentations.show
|
||||||
|
);
|
||||||
|
})
|
||||||
|
segmentation.config.visibility.setSegmentationRepresentationVisibility(
|
||||||
|
viewportId,
|
||||||
|
{
|
||||||
|
segmentationId: segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
||||||
|
},
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let arr = []
|
||||||
|
for (let i = 0; i < segmentList.length; i++) {
|
||||||
|
let item = segmentList[i]
|
||||||
|
let params = {
|
||||||
|
SegmentationId: item.Id,
|
||||||
|
PageSize: 9999,
|
||||||
|
PageIndex: 1,
|
||||||
|
}
|
||||||
|
let r = await getSegmentList(params)
|
||||||
|
if (r.IsSuccess) {
|
||||||
|
let segments = r.Result.CurrentPageData
|
||||||
|
segments.forEach(s => {
|
||||||
|
let obj = {
|
||||||
|
segmentationId: item.Id,
|
||||||
|
segmentIndex: s.SegmentNumber,
|
||||||
|
view: SegmentConfig.InactiveSegmentations.show
|
||||||
|
}
|
||||||
|
if (item.Id === segmentationId) {
|
||||||
|
obj.view = true
|
||||||
|
}
|
||||||
|
arr.push(obj)
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
viewBidirectional(arr, viewportId)
|
||||||
|
}
|
||||||
|
function viewSegmentation(item, viewportId) {
|
||||||
|
segmentation.config.visibility.setSegmentationRepresentationVisibility(
|
||||||
|
viewportId,
|
||||||
|
{
|
||||||
|
segmentationId: item.segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
||||||
|
},
|
||||||
|
item.view
|
||||||
|
);
|
||||||
|
viewBidirectional(item.segments, viewportId)
|
||||||
|
}
|
||||||
|
async function jumpBidirectional(item, viewportId, volumeId) {
|
||||||
|
// DicomEvent.$emit('jumpBidirectional', item)
|
||||||
|
if (item.bidirectional) {
|
||||||
|
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
|
console.log(an, 'an')
|
||||||
|
if (!an) return false
|
||||||
|
if (['viewport-MPR-1', 'viewport-MPR-2'].includes(viewportId)) return false
|
||||||
|
const renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(viewportId)
|
||||||
|
let key = Object.keys(an.data.cachedStats)[0]; // referencedImageId
|
||||||
|
if (key) {
|
||||||
|
let sliceIndex = key.split("?")[1].split("&")[0].split("=")[1]
|
||||||
|
csUtils.jumpToSlice(viewport.element, { imageIndex: sliceIndex });
|
||||||
|
} else {
|
||||||
|
const points = an.data.handles.points;
|
||||||
|
const worldPoint = points[0]; // 取一个点
|
||||||
|
let volume = cache.getVolume(volumeId)
|
||||||
|
let { imageData, numFrames } = volume
|
||||||
|
const ijk = imageData.worldToIndex(worldPoint);
|
||||||
|
const sliceIndex = Math.abs(Math.round(ijk[2]));
|
||||||
|
// console.log(sliceIndex, 'sliceIndex')
|
||||||
|
csUtils.jumpToSlice(viewport.element, { imageIndex: numFrames - sliceIndex - 1 });
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function viewSegment(item, viewportId) {
|
||||||
|
segmentation.config.visibility.setSegmentIndexVisibility(viewportId, {
|
||||||
|
segmentationId: item.segmentationId,
|
||||||
|
type: csToolsEnums.SegmentationRepresentations.Labelmap,
|
||||||
|
}, item.segmentIndex, item.view)
|
||||||
|
viewBidirectional([item], viewportId)
|
||||||
|
}
|
||||||
|
function viewBidirectional(arr, viewportId) {
|
||||||
|
for (let j = 0; j < arr.length; j++) {
|
||||||
|
let item = arr[j]
|
||||||
|
let bidirectional = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === item.segmentationId && i.metadata.segmentIndex === item.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
|
// item.bidirectionalView = view
|
||||||
|
if (!bidirectional) continue
|
||||||
|
let view = item.view
|
||||||
|
if (item.hasOwnProperty('bidirectionalView')) view = item.bidirectionalView
|
||||||
|
annotation.visibility.setAnnotationVisibility(bidirectional.annotationUID, view)
|
||||||
|
}
|
||||||
|
resetViewport(viewportId)
|
||||||
|
}
|
||||||
|
function resetViewport(viewportId) {
|
||||||
|
let renderingEngine = getRenderingEngine(renderingEngineId)
|
||||||
|
const viewport = renderingEngine.getViewport(viewportId)
|
||||||
|
viewport.render()
|
||||||
|
}
|
||||||
|
function changeColor(item, viewportId) {
|
||||||
|
segmentation.config.color.setSegmentIndexColor(viewportId, item.segmentationId, item.segmentIndex, hex2Rgb(item.color))
|
||||||
|
}
|
||||||
|
async function renderSegmentation(series, visitInfo, viewportId, SegmentConfig, RenderingEngineId, Segment = null, actionConfiguration) {
|
||||||
|
try {
|
||||||
|
// console.log(segmentation, 'segmentation')
|
||||||
|
renderingEngineId = RenderingEngineId
|
||||||
|
await removeSegmentFromViewport(viewportId)
|
||||||
|
let data = {
|
||||||
|
SeriesId: series.Id,
|
||||||
|
VisitTaskId: visitInfo.VisitTaskId,
|
||||||
|
PageSize: 9999,
|
||||||
|
PageIndex: 1,
|
||||||
|
}
|
||||||
|
let segmentationId = null;
|
||||||
|
let segmentIndex = null;
|
||||||
|
let res = await getSegmentationList(data);
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
let list = res.Result.CurrentPageData;
|
||||||
|
for (let i = 0; i < list.length; i++) {
|
||||||
|
let item = list[i]
|
||||||
|
if (!segmentationId) segmentationId = item.Id
|
||||||
|
await createSegmentation(viewportId, series.SeriesInstanceUid, item.Id)
|
||||||
|
if (item.SEGUrl) await readSegmentation(item.SEGUrl, series, item.Id)
|
||||||
|
createSegmentationRepresentation(viewportId, item.Id)
|
||||||
|
if (!viewportInfo[viewportId]) {
|
||||||
|
viewportInfo[viewportId] = [item.Id]
|
||||||
|
} else {
|
||||||
|
viewportInfo[viewportId].push(item.Id)
|
||||||
|
}
|
||||||
|
let params = {
|
||||||
|
SegmentationId: item.Id,
|
||||||
|
PageSize: 9999,
|
||||||
|
PageIndex: 1,
|
||||||
|
}
|
||||||
|
let r = await getSegmentList(params)
|
||||||
|
if (r.IsSuccess) {
|
||||||
|
let segments = r.Result.CurrentPageData
|
||||||
|
segments.forEach(s => {
|
||||||
|
if (!segmentIndex) segmentIndex = s.SegmentNumber
|
||||||
|
let SegmentJson = s.SegmentJson ? JSON.parse(s.SegmentJson) : {};
|
||||||
|
segmentation.segmentIndex.setActiveSegmentIndex(s.SegmentationId, s.SegmentNumber);
|
||||||
|
segmentation.config.color.setSegmentIndexColor(viewportId, s.SegmentationId, s.SegmentNumber, hex2Rgb(s.ColorRgb))
|
||||||
|
segmentation.segmentLocking.setSegmentIndexLocked(s.SegmentationId, s.SegmentNumber, true)
|
||||||
|
if (SegmentJson.bidirectional) {
|
||||||
|
let an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === s.SegmentationId && i.metadata.segmentIndex === SegmentJson.bidirectional.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
|
if (!an) {
|
||||||
|
let { majorAxis, minorAxis } = SegmentJson.bidirectional
|
||||||
|
// createSegmentConfiguration(s.SegmentNumber, s.SegmentationId, viewportId, actionConfiguration)
|
||||||
|
SegmentBidirectionalTool.hydrate(viewportId, [majorAxis, minorAxis], {
|
||||||
|
segmentIndex: s.SegmentNumber,
|
||||||
|
segmentationId: s.SegmentationId,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
an = annotation.state.getAllAnnotations().find(i => i.metadata.segmentationId === s.SegmentationId && i.metadata.segmentIndex === SegmentJson.bidirectional.segmentIndex && i.metadata.toolName === "SegmentBidirectional");
|
||||||
|
if (an) {
|
||||||
|
annotation.locking.setAnnotationLocked(an.annotationUID, true)
|
||||||
|
annotation.visibility.setAnnotationVisibility(an.annotationUID, true)
|
||||||
|
}
|
||||||
|
console.log(an, 'an')
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
}
|
||||||
|
if (segmentationId && segmentIndex) {
|
||||||
|
selectSegment(viewportId, segmentationId, segmentIndex)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Segment) {
|
||||||
|
jumpBidirectional(Segment, viewportId, series.SeriesInstanceUid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
readingSegmentByConfig(series, visitInfo, viewportId, segmentationId, SegmentConfig)
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export {
|
||||||
|
createSegmentation,
|
||||||
|
createSegmentationRepresentation,
|
||||||
|
readSegmentation,
|
||||||
|
renderSegmentation,
|
||||||
|
readingSegmentByConfig,
|
||||||
|
selectSegment,
|
||||||
|
selectSegmentation,
|
||||||
|
viewSegmentation,
|
||||||
|
viewSegment,
|
||||||
|
jumpBidirectional,
|
||||||
|
viewBidirectional,
|
||||||
|
changeColor,
|
||||||
|
resetViewport
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
|
import vtkColorTransferFunction from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction";
|
||||||
import vtkPiecewiseFunction from "@kitware/vtk.js/Common/DataModel/PiecewiseFunction";
|
import vtkPiecewiseFunction from "@kitware/vtk.js/Common/DataModel/PiecewiseFunction";
|
||||||
|
import { Scale } from "@kitware/vtk.js/Rendering/Core/ColorTransferFunction/Constants";
|
||||||
import { cache, metaData, utilities } from "@cornerstonejs/core";
|
import { cache, metaData, utilities } from "@cornerstonejs/core";
|
||||||
|
|
||||||
const { getColormap } = utilities.colormap;
|
const { getColormap } = utilities.colormap;
|
||||||
|
|
@ -14,7 +15,7 @@ function getWindowCenterFromVolumeId(volumeId) {
|
||||||
? voiLutModule.windowCenter[0]
|
? voiLutModule.windowCenter[0]
|
||||||
: voiLutModule?.windowCenter;
|
: voiLutModule?.windowCenter;
|
||||||
const center = Number(rawCenter);
|
const center = Number(rawCenter);
|
||||||
return Number.isFinite(center) ? center : null;
|
return center;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function setPetColorMapTransferFunctionForVolumeActor({
|
export default function setPetColorMapTransferFunctionForVolumeActor({
|
||||||
|
|
@ -33,7 +34,25 @@ export default function setPetColorMapTransferFunctionForVolumeActor({
|
||||||
|
|
||||||
const center = getWindowCenterFromVolumeId(volumeId);
|
const center = getWindowCenterFromVolumeId(volumeId);
|
||||||
const upper = center > 1 ? center : 5;
|
const upper = center > 1 ? center : 5;
|
||||||
cfun.setMappingRange(1, upper);
|
const safeUpper = Number.isFinite(upper) && upper > 0 ? upper : 5;
|
||||||
|
const rangeMin = 0;
|
||||||
|
const rangeMax = safeUpper;
|
||||||
|
cfun.setScale(Scale.LOG10);
|
||||||
|
cfun.setMappingRange(rangeMin, rangeMax);
|
||||||
|
|
||||||
volumeActor.getProperty().setRGBTransferFunction(0, cfun);
|
volumeActor.getProperty().setRGBTransferFunction(0, cfun);
|
||||||
|
//低信号更明显,系数可以更小
|
||||||
|
const thresholdValue0 = Math.max(rangeMin, rangeMax * 0.002);
|
||||||
|
const thresholdValue1 = Math.max(thresholdValue0, rangeMax * 0.02);
|
||||||
|
const delta = Math.abs(rangeMax - rangeMin) * 0.001;
|
||||||
|
const threshold0MinusDelta = Math.max(rangeMin, thresholdValue0 - delta);
|
||||||
|
|
||||||
|
const ofun = vtkPiecewiseFunction.newInstance();
|
||||||
|
ofun.addPoint(rangeMin, 0.0);
|
||||||
|
ofun.addPoint(threshold0MinusDelta, 0.0);
|
||||||
|
//低信号更明显,系数可以更小
|
||||||
|
ofun.addPoint(thresholdValue0, 0.08);
|
||||||
|
ofun.addPoint(thresholdValue1, 0.9);
|
||||||
|
ofun.addPoint(rangeMax, 1.0);
|
||||||
|
volumeActor.getProperty().setScalarOpacity(0, ofun);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -311,6 +311,15 @@ const config = {
|
||||||
'isDisabled': false,
|
'isDisabled': false,
|
||||||
'disabledReason': ''
|
'disabledReason': ''
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
'name': '定圆工具',
|
||||||
|
'icon': 'oval',
|
||||||
|
'toolName': 'FixedRadiusCircleROI',
|
||||||
|
'props': ['radius', 'area', 'mean', 'max', 'stdDev'],
|
||||||
|
'i18nKey': 'trials:reading:button:fixedCircle',
|
||||||
|
'isDisabled': false,
|
||||||
|
'disabledReason': ''
|
||||||
|
}
|
||||||
],
|
],
|
||||||
'customizeStandardsNoneDicom': [
|
'customizeStandardsNoneDicom': [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -28,10 +28,12 @@ class FixedRadiusCircleROITool extends cornerstoneTools.CircleROITool {
|
||||||
preventHandleOutsideImage: false,
|
preventHandleOutsideImage: false,
|
||||||
storePointData: false,
|
storePointData: false,
|
||||||
centerPointRadius: 0,
|
centerPointRadius: 0,
|
||||||
radius: 10, // Default radius in mm
|
calculateStats: true,
|
||||||
|
radius: 6, // Default radius in mm
|
||||||
radiusUnit: 'mm',
|
radiusUnit: 'mm',
|
||||||
statsCalculator: BasicStatsCalculator,
|
statsCalculator: BasicStatsCalculator,
|
||||||
getTextLines: defaultGetTextLines,
|
getTextLines: defaultGetTextLines,
|
||||||
|
simplified: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
) {
|
) {
|
||||||
|
|
@ -67,9 +69,12 @@ class FixedRadiusCircleROITool extends cornerstoneTools.CircleROITool {
|
||||||
);
|
);
|
||||||
|
|
||||||
const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
const FrameOfReferenceUID = viewport.getFrameOfReferenceUID();
|
||||||
|
const targetId = this.getTargetId(viewport);
|
||||||
|
|
||||||
// Calculate end point based on fixed radius
|
// Calculate end point based on fixed radius
|
||||||
const radius = this.configuration.radius || 10;
|
const radius = Number.isFinite(this.configuration.radius)
|
||||||
|
? this.configuration.radius
|
||||||
|
: 10;
|
||||||
// viewUp is a normalized vector.
|
// viewUp is a normalized vector.
|
||||||
// We want a point 'radius' distance away from center.
|
// We want a point 'radius' distance away from center.
|
||||||
// We can use viewUp or any vector in the plane.
|
// We can use viewUp or any vector in the plane.
|
||||||
|
|
@ -106,7 +111,20 @@ class FixedRadiusCircleROITool extends cornerstoneTools.CircleROITool {
|
||||||
points: [[...worldPos], [...endPos]],
|
points: [[...worldPos], [...endPos]],
|
||||||
activeHandleIndex: null,
|
activeHandleIndex: null,
|
||||||
},
|
},
|
||||||
cachedStats: {},
|
cachedStats: {
|
||||||
|
[targetId]: {
|
||||||
|
Modality: null,
|
||||||
|
radius: null,
|
||||||
|
radiusUnit: null,
|
||||||
|
area: null,
|
||||||
|
mean: null,
|
||||||
|
stdDev: null,
|
||||||
|
max: null,
|
||||||
|
isEmptyArea: null,
|
||||||
|
areaUnit: null,
|
||||||
|
modalityUnit: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -180,9 +198,11 @@ class FixedRadiusCircleROITool extends cornerstoneTools.CircleROITool {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FixedRadiusCircleROITool;
|
|
||||||
function defaultGetTextLines(data, targetId) {
|
function defaultGetTextLines(data, targetId) {
|
||||||
const cachedVolumeStats = data.cachedStats[targetId];
|
const cachedVolumeStats = data?.cachedStats?.[targetId];
|
||||||
|
if (!cachedVolumeStats) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
const {
|
const {
|
||||||
radius,
|
radius,
|
||||||
radiusUnit,
|
radiusUnit,
|
||||||
|
|
@ -195,32 +215,33 @@ function defaultGetTextLines(data, targetId) {
|
||||||
modalityUnit,
|
modalityUnit,
|
||||||
} = cachedVolumeStats;
|
} = cachedVolumeStats;
|
||||||
const textLines = [];
|
const textLines = [];
|
||||||
|
if (csUtils.isNumber(radius)) {
|
||||||
if (radius) {
|
|
||||||
const radiusLine = isEmptyArea
|
const radiusLine = isEmptyArea
|
||||||
? `Radius: Oblique not supported`
|
? `Radius: Oblique not supported`
|
||||||
: `Radius: ${csUtils.roundNumber(radius)} ${radiusUnit}`;
|
: `Radius: ${csUtils.roundNumber(radius)} ${radiusUnit}`;
|
||||||
textLines.push(radiusLine);
|
textLines.push(radiusLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (area) {
|
if (csUtils.isNumber(area)) {
|
||||||
const areaLine = isEmptyArea
|
const areaLine = isEmptyArea
|
||||||
? `Area: Oblique not supported`
|
? `Area: Oblique not supported`
|
||||||
: `Area: ${csUtils.roundNumber(area)} ${areaUnit}`;
|
: `Area: ${csUtils.roundNumber(area)} ${areaUnit}`;
|
||||||
textLines.push(areaLine);
|
textLines.push(areaLine);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mean) {
|
if (csUtils.isNumber(mean)) {
|
||||||
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`);
|
textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (max) {
|
if (csUtils.isNumber(max)) {
|
||||||
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`);
|
textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdDev) {
|
if (csUtils.isNumber(stdDev)) {
|
||||||
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`);
|
textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return textLines;
|
return textLines;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export default FixedRadiusCircleROITool;
|
||||||
|
|
|
||||||
|
|
@ -302,7 +302,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3 ) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -358,7 +358,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -276,7 +276,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -290,7 +290,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,14 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form v-if="globalForm.taskList.length > 0" ref="globalRuleForm" :model="globalForm" class="global-form">
|
<el-form v-if="globalForm.taskList.length > 0" ref="globalRuleForm" :model="globalForm" class="global-form">
|
||||||
<el-table
|
<el-table v-loading="loading" :data="globalForm.taskList">
|
||||||
v-loading="loading"
|
|
||||||
:data="globalForm.taskList"
|
|
||||||
>
|
|
||||||
<!-- 访视名称 -->
|
<!-- 访视名称 -->
|
||||||
<el-table-column
|
<el-table-column prop="BlindName" :label="$t('trials:globalReview:table:visitName')" show-overflow-tooltip
|
||||||
prop="BlindName"
|
width="150" />
|
||||||
:label="$t('trials:globalReview:table:visitName')"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="150"
|
|
||||||
/>
|
|
||||||
<!-- 评估结果 -->
|
<!-- 评估结果 -->
|
||||||
<el-table-column
|
<el-table-column :label="$t('trials:globalReview:table:evaluationRes')" align="center" prop="">
|
||||||
:label="$t('trials:globalReview:table:evaluationRes')"
|
|
||||||
align="center"
|
|
||||||
prop=""
|
|
||||||
>
|
|
||||||
<template>
|
<template>
|
||||||
<el-table-column
|
<el-table-column v-for="(qs, index) in globalInfo.evaluationQsList" :key="index" prop="" :label="qs"
|
||||||
v-for="(qs,index) in globalInfo.evaluationQsList"
|
show-overflow-tooltip width="150">
|
||||||
:key="index"
|
|
||||||
prop=""
|
|
||||||
:label="qs"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="150"
|
|
||||||
>
|
|
||||||
<!-- <template slot-scope="scope">
|
<!-- <template slot-scope="scope">
|
||||||
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
||||||
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
||||||
|
|
@ -35,10 +18,14 @@
|
||||||
</div>
|
</div>
|
||||||
</template> -->
|
</template> -->
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<template v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType ===0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType ===4)">
|
<template
|
||||||
<div v-if="scope.row.BeforeQuestionList.length>index && scope.row.BeforeQuestionList[index].Answer" :style="{color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null}">
|
v-if="(scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType === 1 || scope.row.BeforeQuestionList[index].GlobalReadingShowType === 5)) || (!scope.row.IsBaseLine && (scope.row.BeforeQuestionList[index].GlobalReadingShowType === 2 || scope.row.BeforeQuestionList[index].GlobalReadingShowType === 6)) || (scope.row.BeforeQuestionList[index].GlobalReadingShowType === 0 || scope.row.BeforeQuestionList[index].GlobalReadingShowType === 4)">
|
||||||
|
<div v-if="scope.row.BeforeQuestionList.length > index && scope.row.BeforeQuestionList[index].Answer"
|
||||||
|
:style="{ color: scope.row.BeforeQuestionList[index].IsGlobalAnswer ? '#f66' : null }">
|
||||||
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
<span v-if="scope.row.BeforeQuestionList[index].DictionaryCode">
|
||||||
{{ $fd(scope.row.BeforeQuestionList[index].DictionaryCode,parseInt(scope.row.BeforeQuestionList[index].Answer)) }}
|
{{
|
||||||
|
$fd(scope.row.BeforeQuestionList[index].DictionaryCode, parseInt(scope.row.BeforeQuestionList[index].Answer))
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
|
<span v-else>{{ scope.row.BeforeQuestionList[index].Answer }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -49,211 +36,145 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 是否同意访视结果 -->
|
<!-- 是否同意访视结果 -->
|
||||||
<el-table-column
|
<el-table-column prop="" :label="$t('trials:globalReview:table:isAgreeEvaluationRes')" show-overflow-tooltip
|
||||||
prop=""
|
width="170">
|
||||||
:label="$t('trials:globalReview:table:isAgreeEvaluationRes')"
|
|
||||||
show-overflow-tooltip
|
|
||||||
width="170"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-form-item
|
<el-form-item v-if="readingTaskState < 2" :prop="`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`"
|
||||||
v-if="readingTaskState<2"
|
label="" :rules="[
|
||||||
:prop="`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`"
|
|
||||||
label=""
|
|
||||||
:rules="[
|
|
||||||
{ required: true, message: $t('common:ruleMessage:select'), trigger: ['change', 'blur'] },
|
{ required: true, message: $t('common:ruleMessage:select'), trigger: ['change', 'blur'] },
|
||||||
]"
|
]" class="form-item">
|
||||||
class="form-item"
|
<el-radio-group v-model="globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]"
|
||||||
>
|
@change="handleAgreeOrNotChange(scope.$index, scope.row.AgreeOrNot[0].GlobalAnswerType)">
|
||||||
<el-radio-group
|
<el-radio v-for="item of $d.ReadingYesOrNo" :key="'AgreeOrNot' + item.value" :label="String(item.value)">
|
||||||
v-model="globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]"
|
|
||||||
@change="handleAgreeOrNotChange(scope.$index,scope.row.AgreeOrNot[0].GlobalAnswerType)"
|
|
||||||
>
|
|
||||||
<el-radio
|
|
||||||
v-for="item of $d.ReadingYesOrNo"
|
|
||||||
:key="'AgreeOrNot' + item.value"
|
|
||||||
:label="String(item.value)"
|
|
||||||
>
|
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 1" type="primary">
|
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 1"
|
||||||
|
type="primary">
|
||||||
{{ $fd('ReadingYesOrNo', parseInt(scope.row.AgreeOrNot[0].Answer)) }}
|
{{ $fd('ReadingYesOrNo', parseInt(scope.row.AgreeOrNot[0].Answer)) }}
|
||||||
</el-tag>
|
</el-tag>
|
||||||
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 0" type="danger"> {{ $fd('ReadingYesOrNo',parseInt(scope.row.AgreeOrNot[0].Answer)) }}</el-tag>
|
<el-tag v-else-if="scope.row.AgreeOrNot.length > 0 && parseInt(scope.row.AgreeOrNot[0].Answer) === 0"
|
||||||
|
type="danger"> {{ $fd('ReadingYesOrNo', parseInt(scope.row.AgreeOrNot[0].Answer)) }}</el-tag>
|
||||||
<span v-else />
|
<span v-else />
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
|
|
||||||
<!-- 调整后结果 -->
|
<!-- 调整后结果 -->
|
||||||
<el-table-column
|
<el-table-column :label="$t('trials:globalReview:table:adjustedRes')" align="center" prop="">
|
||||||
:label="$t('trials:globalReview:table:adjustedRes')"
|
|
||||||
align="center"
|
|
||||||
prop=""
|
|
||||||
>
|
|
||||||
<template v-for="(qs, index) in globalInfo.adjustedQsList">
|
<template v-for="(qs, index) in globalInfo.adjustedQsList">
|
||||||
<el-table-column
|
<el-table-column v-if="qs.isShow" :key="index" prop="" :label="qs.questionName" show-overflow-tooltip
|
||||||
v-if="qs.isShow"
|
:min-width="index === 3 ? '200' : '200'">
|
||||||
:key="index"
|
|
||||||
prop=""
|
|
||||||
:label="qs.questionName"
|
|
||||||
show-overflow-tooltip
|
|
||||||
:min-width="index === 3 ? '200' : '200'"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<div v-if="readingTaskState<2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
|
<div
|
||||||
|
v-if="readingTaskState < 2 && (scope.row.AfterQuestionList[index].GlobalReadingShowType === 0 || (scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 1) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].GlobalReadingShowType === 2))">
|
||||||
<!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
|
<!-- <span v-if="(scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 2) || (!scope.row.IsBaseLine && scope.row.AfterQuestionList[index].LimitEdit === 1)">
|
||||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
|
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].VisitAnswer)) }}
|
||||||
</span> -->
|
</span> -->
|
||||||
<el-form-item
|
<el-form-item style="margin-bottom: 0;"
|
||||||
style="margin-bottom: 0;"
|
|
||||||
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : scope.row.AfterQuestionList[index].GlobalAnswerType}`"
|
:prop="`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : scope.row.AfterQuestionList[index].GlobalAnswerType}`"
|
||||||
label=""
|
label="" :rules="[
|
||||||
:rules="[
|
|
||||||
{ required: parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0, message: $t('common:ruleMessage:specify'), trigger: ['change', 'blur'] },
|
{ required: parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0, message: $t('common:ruleMessage:specify'), trigger: ['change', 'blur'] },
|
||||||
]"
|
]">
|
||||||
>
|
<label
|
||||||
<label v-if="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0" />
|
v-if="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) === 0" />
|
||||||
<!-- 裁判问题 -->
|
<!-- 裁判问题 -->
|
||||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 0">
|
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 0">
|
||||||
<el-tooltip v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId?scope.row.AfterQuestionList[index].QuestionId:String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])" placement="top-start">
|
<el-tooltip
|
||||||
|
v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])"
|
||||||
|
class="item" effect="dark"
|
||||||
|
:content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`], scope.row.AfterQuestionList[index])"
|
||||||
|
placement="top-start">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||||
style="width:90%;"
|
style="width:90%;"
|
||||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0">
|
||||||
>
|
|
||||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||||
<el-option
|
<el-option v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')" :key="val"
|
||||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
:label="val" :value="val" />
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
:value="val"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
<template
|
||||||
<el-option
|
v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
<el-option v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||||
v-show="item.value!==-1"
|
v-show="item.value !== -1" :key="item.id" :value="String(item.value)" :label="item.label"
|
||||||
:key="item.id"
|
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)" />
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||||
<el-option
|
<el-option v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
:key="item.id" :value="String(item.value)"
|
||||||
:key="item.id"
|
|
||||||
:value="String(item.value)"
|
|
||||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)"
|
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)"
|
||||||
:label="item.label"
|
:label="item.label" />
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-select
|
<el-select v-else
|
||||||
v-else
|
|
||||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||||
style="width:90%;"
|
style="width:90%;"
|
||||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0">
|
||||||
>
|
|
||||||
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
<template v-if="scope.row.AfterQuestionList[index].TypeValue">
|
||||||
<el-option
|
<el-option v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')" :key="val"
|
||||||
v-for="val in scope.row.AfterQuestionList[index].TypeValue.split('|')"
|
:label="val" :value="val" />
|
||||||
:key="val"
|
|
||||||
:label="val"
|
|
||||||
:value="val"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
<template
|
||||||
|
v-else-if="scope.row.AfterQuestionList[index].DictionaryCode && scope.row.AfterQuestionList[index].QuestionType === 13">
|
||||||
<template v-if="getLesionCount(scope.row.LesionCountList, 0)">
|
<template v-if="getLesionCount(scope.row.LesionCountList, 0)">
|
||||||
<el-option
|
<el-option v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
v-show="item.value !== -1 && item.value !== 1 && item.value !== 3" :key="item.id"
|
||||||
v-show="item.value!==-1 && item.value !== 1 && item.value !== 3"
|
:value="String(item.value)" :label="item.label"
|
||||||
:key="item.id"
|
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)" />
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="getLesionCount(scope.row.LesionCountList, 1)">
|
<template v-else-if="getLesionCount(scope.row.LesionCountList, 1)">
|
||||||
<el-option
|
<el-option v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
v-show="item.value !== -1 && item.value !== 1 && item.value !== 6" :key="item.id"
|
||||||
v-show="item.value!==-1 && item.value !== 1 && item.value !== 6"
|
:value="String(item.value)" :label="item.label"
|
||||||
:key="item.id"
|
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)" />
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<el-option
|
<el-option v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
v-show="item.value === 1 || item.value === 2 || item.value === 4" :key="item.id"
|
||||||
v-show="item.value === 1 || item.value === 2 || item.value === 4"
|
:value="String(item.value)" :label="item.label"
|
||||||
:key="item.id"
|
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)" />
|
||||||
:value="String(item.value)"
|
|
||||||
:label="item.label"
|
|
||||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName,scope.row)) === String(item.value)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
</template>
|
</template>
|
||||||
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
<template v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||||
<el-option
|
<el-option v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
||||||
v-for="item of $d[scope.row.AfterQuestionList[index].DictionaryCode]"
|
v-show="item.value !== 6" :key="item.id" :value="String(item.value)"
|
||||||
v-show="item.value !== 6"
|
|
||||||
:key="item.id"
|
|
||||||
:value="String(item.value)"
|
|
||||||
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)"
|
:disabled="String(getBeforeAnswer(scope.row.AfterQuestionList[index].QuestionName, scope.row)) === String(item.value)"
|
||||||
:label="item.label"
|
:label="item.label" />
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
<!-- 评估更新类型 GlobalAnswerType:3 -->
|
<!-- 评估更新类型 GlobalAnswerType:3 -->
|
||||||
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
<template v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 3">
|
||||||
<el-tooltip v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" class="item" effect="dark" :content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)" placement="top-start">
|
<el-tooltip
|
||||||
|
v-if="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)"
|
||||||
|
class="item" effect="dark"
|
||||||
|
:content="getText(globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`], scope.row.AfterQuestionList[index], scope.row.AfterQuestionList[index].GlobalAnswerType)"
|
||||||
|
placement="top-start">
|
||||||
<el-select
|
<el-select
|
||||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||||
style="width:90%;"
|
style="width:90%;"
|
||||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0">
|
||||||
>
|
<el-option v-for="val in globalInfo.assessTypeList"
|
||||||
<el-option
|
|
||||||
v-for="val in globalInfo.assessTypeList"
|
|
||||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
|
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
|
||||||
:key="val.Code"
|
:key="val.Code" :label="language === 'en' ? val.Value : val.ValueCN" :value="val.Code" />
|
||||||
:label="language === 'en'?val.Value:val.ValueCN"
|
|
||||||
:value="val.Code"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-tooltip>
|
</el-tooltip>
|
||||||
<el-select
|
<el-select v-else
|
||||||
v-else
|
|
||||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].GlobalAnswerType}`]"
|
||||||
style="width:90%;"
|
style="width:90%;"
|
||||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0">
|
||||||
>
|
<el-option v-for="val in globalInfo.assessTypeList"
|
||||||
<el-option
|
|
||||||
v-for="val in globalInfo.assessTypeList"
|
|
||||||
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
|
v-show="(scope.row.IsBaseLine && val.IsBaseLineUse) || (!scope.row.IsBaseLine && val.IsFollowVisitUse)"
|
||||||
:key="val.Code"
|
:key="val.Code" :label="language === 'en' ? val.Value : val.ValueCN" :value="val.Code" />
|
||||||
:label="language === 'en'?val.Value:val.ValueCN"
|
|
||||||
:value="val.Code"
|
|
||||||
/>
|
|
||||||
</el-select>
|
</el-select>
|
||||||
</template>
|
</template>
|
||||||
<el-input
|
<el-input v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 1"
|
||||||
v-if="scope.row.AfterQuestionList[index].GlobalAnswerType === 1"
|
|
||||||
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
v-model="globalForm[`${scope.$index}${scope.row.AfterQuestionList[index].QuestionId ? scope.row.AfterQuestionList[index].QuestionId : String(scope.row.AfterQuestionList[index].GlobalAnswerType)}`]"
|
||||||
type="textarea"
|
type="textarea" maxlength="100" show-word-limit style="width:90%;" :autosize="{ minRows: 2 }"
|
||||||
maxlength="100"
|
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0" />
|
||||||
show-word-limit
|
|
||||||
style="width:90%;"
|
|
||||||
:autosize="{ minRows: 2 }"
|
|
||||||
:disabled="parseInt(globalForm[`${scope.$index}${scope.row.AgreeOrNot[0].GlobalAnswerType}`]) !== 0"
|
|
||||||
/>
|
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else>
|
||||||
|
|
@ -262,7 +183,9 @@
|
||||||
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
|
{{ getAssessType(scope.row.AfterQuestionList[index].Answer) }}
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
<span v-else-if="scope.row.AfterQuestionList[index].DictionaryCode">
|
||||||
{{ $fd(scope.row.AfterQuestionList[index].DictionaryCode,parseInt(scope.row.AfterQuestionList[index].Answer)) }}
|
{{
|
||||||
|
$fd(scope.row.AfterQuestionList[index].DictionaryCode, parseInt(scope.row.AfterQuestionList[index].Answer))
|
||||||
|
}}
|
||||||
</span>
|
</span>
|
||||||
<span v-else>{{ scope.row.AfterQuestionList[index].Answer }}</span>
|
<span v-else>{{ scope.row.AfterQuestionList[index].Answer }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -270,17 +193,10 @@
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column :label="$t('common:action:action')" width="100">
|
||||||
:label="$t('common:action:action')"
|
|
||||||
width="100"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-button circle :title="$t('trials:globalReview:table:view')" icon="el-icon-view"
|
||||||
circle
|
@click="handleView(scope.row)" />
|
||||||
:title="$t('trials:globalReview:table:view')"
|
|
||||||
icon="el-icon-view"
|
|
||||||
@click="handleView(scope.row)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
|
@ -348,7 +264,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
@ -383,8 +299,10 @@ export default {
|
||||||
}
|
}
|
||||||
answerList.push(obj)
|
answerList.push(obj)
|
||||||
})
|
})
|
||||||
answerList.push({ questionId: '', globalAnswerType: item.AgreeOrNot[0].GlobalAnswerType,
|
answerList.push({
|
||||||
answer: this.globalForm[ `${index}${item.AgreeOrNot[0].GlobalAnswerType}`] })
|
questionId: '', globalAnswerType: item.AgreeOrNot[0].GlobalAnswerType,
|
||||||
|
answer: this.globalForm[`${index}${item.AgreeOrNot[0].GlobalAnswerType}`]
|
||||||
|
})
|
||||||
|
|
||||||
visitTaskAnswerList.push({ visitTaskId: item.VisitTaskId, answerList: answerList })
|
visitTaskAnswerList.push({ visitTaskId: item.VisitTaskId, answerList: answerList })
|
||||||
})
|
})
|
||||||
|
|
@ -462,17 +380,21 @@ export default {
|
||||||
color: #F56C6C;
|
color: #F56C6C;
|
||||||
margin-right: 4px;
|
margin-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-textarea .el-input__count {
|
::v-deep .el-textarea .el-input__count {
|
||||||
background: rgba(0, 0, 0, 0);
|
background: rgba(0, 0, 0, 0);
|
||||||
line-height: normal;
|
line-height: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .el-form-item {
|
::v-deep .el-form-item {
|
||||||
margin-bottom: 0px;
|
margin-bottom: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.global-form {
|
.global-form {
|
||||||
::v-deep .el-form-item__content {
|
::v-deep .el-form-item__content {
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
::v-deep .form-item .el-form-item__error {
|
::v-deep .form-item .el-form-item__error {
|
||||||
top: 60%;
|
top: 60%;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -355,7 +355,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -349,7 +349,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.globalInfo.trialId}&subjectCode=${this.globalInfo.subjectCode}&subjectId=${this.globalInfo.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -404,7 +404,7 @@ export default {
|
||||||
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
readingTool = isNaN(parseInt(readingTool)) ? null : parseInt(readingTool)
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ export default {
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
||||||
|
|
||||||
var path = "";
|
var path = "";
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode
|
||||||
}&subjectId=${this.rowData.SubjectId
|
}&subjectId=${this.rowData.SubjectId
|
||||||
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||||
|
|
@ -273,7 +273,7 @@ export default {
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId;
|
||||||
|
|
||||||
var path = "";
|
var path = "";
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode
|
||||||
}&subjectId=${this.rowData.SubjectId}&visitTaskId=${task.VisitTaskId
|
}&subjectId=${this.rowData.SubjectId}&visitTaskId=${task.VisitTaskId
|
||||||
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`;
|
||||||
|
|
|
||||||
|
|
@ -258,7 +258,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.rowData.IsReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.rowData.IsReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
|
|
|
||||||
|
|
@ -146,7 +146,7 @@ export default {
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
|
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2|| readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
|
|
|
||||||
|
|
@ -164,7 +164,7 @@ export default {
|
||||||
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
var trialReadingCriterionId = this.rowData.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
|
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.rowData.SubjectCode}&subjectId=${this.rowData.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
|
|
|
||||||
|
|
@ -795,7 +795,7 @@ export default {
|
||||||
var trialReadingCriterionId = row.TrialReadingCriterionId
|
var trialReadingCriterionId = row.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
|
|
||||||
if (readingTool === 0 || readingTool === 2 ) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}&key=${new Date().getTime()}`
|
||||||
|
|
|
||||||
|
|
@ -452,7 +452,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||||
var path = ''
|
var path = ''
|
||||||
if (readingTool === 0 || readingTool === 2) {
|
if (readingTool === 0 || readingTool === 2 || readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${this.subjectCode}&subjectId=${this.subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -953,7 +953,7 @@ export default {
|
||||||
lookReadingResults(row) {
|
lookReadingResults(row) {
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path
|
var path
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0 || row.ReadingTool === 2|| row.ReadingTool === 3) {
|
||||||
path = `/readingDicoms?trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/readingDicoms?trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,7 @@ export default {
|
||||||
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path = ''
|
var path = ''
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0 || row.ReadingTool === 2 || row.ReadingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ export default {
|
||||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||||
var criterionType = this.$router.currentRoute.query.criterionType
|
var criterionType = this.$router.currentRoute.query.criterionType
|
||||||
var path = ''
|
var path = ''
|
||||||
if (this.readingTool === 0 || this.readingTool === 2 ) {
|
if (this.readingTool === 0 || this.readingTool === 2 || this.readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${visitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${this.readingTool}&TokenKey=${this.token}`
|
||||||
|
|
|
||||||
|
|
@ -368,7 +368,7 @@ export default {
|
||||||
)
|
)
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path = ''
|
var path = ''
|
||||||
if (this.readingTool === 0 || this.readingTool === 2) {
|
if (this.readingTool === 0 || this.readingTool === 2|| this.readingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${this.trialId}&isReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}&criterionType=${this.criterionType}&readingTool=${this.readingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -614,7 +614,7 @@ export default {
|
||||||
}
|
}
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path
|
var path
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0 || row.ReadingTool === 2|| row.ReadingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -1202,7 +1202,7 @@ export default {
|
||||||
}
|
}
|
||||||
var token = getToken()
|
var token = getToken()
|
||||||
var path
|
var path
|
||||||
if (row.ReadingTool === 0 || row.ReadingTool === 2) {
|
if (row.ReadingTool === 0 || row.ReadingTool === 2 || row.ReadingTool === 3) {
|
||||||
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
} else {
|
} else {
|
||||||
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
|
||||||
|
|
|
||||||
|
|
@ -4,123 +4,63 @@
|
||||||
<template>
|
<template>
|
||||||
<el-form v-loading="loading">
|
<el-form v-loading="loading">
|
||||||
<!-- 仲裁对象 -->
|
<!-- 仲裁对象 -->
|
||||||
<el-form-item
|
<el-form-item :label="$t('trials:adRules:title:arbitrationRule')" :label-width="'180px'">
|
||||||
:label="$t('trials:adRules:title:arbitrationRule')"
|
<el-radio-group v-model="JudgyInfo.ArbitrationRule" :disabled="OtherInfo.IsSign">
|
||||||
:label-width="'180px'"
|
<el-radio v-for="item of $d.ArbitrationRule" :key="item.id"
|
||||||
>
|
:disabled="!JudgyInfo.IsReadingTaskViewInOrder || true" :label="item.value" @change="changeArbitrationRule">
|
||||||
<el-radio-group
|
|
||||||
v-model="JudgyInfo.ArbitrationRule"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
>
|
|
||||||
<el-radio
|
|
||||||
v-for="item of $d.ArbitrationRule"
|
|
||||||
:key="item.id"
|
|
||||||
:disabled="!JudgyInfo.IsReadingTaskViewInOrder || true"
|
|
||||||
:label="item.value"
|
|
||||||
@change="changeArbitrationRule"
|
|
||||||
>
|
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-collapse v-model="activeNames" style="border-top:none;">
|
<el-collapse v-model="activeNames" style="border-top:none;">
|
||||||
<el-collapse-item
|
<el-collapse-item v-for="(item, index) of QuestionList" :key="item.ReadingQuestionTrialId"
|
||||||
v-for="(item, index) of QuestionList"
|
style="position: relative;padding:0 10px;" :name="item.ReadingQuestionTrialId">
|
||||||
:key="item.ReadingQuestionTrialId"
|
|
||||||
style="position: relative;padding:0 10px;"
|
|
||||||
:name="item.ReadingQuestionTrialId"
|
|
||||||
>
|
|
||||||
<div slot="title">
|
<div slot="title">
|
||||||
{{ item.PageName }}Q{{ index + 1 }}:{{ item.QuestionName }}
|
{{ item.PageName }}Q{{ index + 1 }}:{{ item.QuestionName }}
|
||||||
</div>
|
</div>
|
||||||
<div style="position: relative">
|
<div style="position: relative">
|
||||||
<el-button
|
<el-button v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
||||||
v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
style="position: absolute; right: 0; top: 0; z-index: 10" size="mini" type="primary"
|
||||||
style="position: absolute; right: 0; top: 0; z-index: 10"
|
:disabled="OtherInfo.IsSign" @click="apply(item.ReadingQuestionTrialId, index)">{{ $t('common:button:save')
|
||||||
size="mini"
|
}}</el-button>
|
||||||
type="primary"
|
<el-button v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
||||||
:disabled="OtherInfo.IsSign"
|
style="position: absolute; right: 60px; top: 0; z-index: 10" size="mini" type="primary"
|
||||||
@click="apply(item.ReadingQuestionTrialId, index)"
|
:disabled="OtherInfo.IsSign" @click="reset(item.ReadingQuestionTrialId, index)">{{ $t('common:button:reset')
|
||||||
>{{ $t('common:button:save') }}</el-button
|
}}</el-button>
|
||||||
>
|
|
||||||
<el-button
|
|
||||||
v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
|
||||||
style="position: absolute; right: 60px; top: 0; z-index: 10"
|
|
||||||
size="mini"
|
|
||||||
type="primary"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
@click="reset(item.ReadingQuestionTrialId, index)"
|
|
||||||
>{{ $t('common:button:reset') }}</el-button
|
|
||||||
>
|
|
||||||
<!-- 产生裁判阅片的条件 -->
|
<!-- 产生裁判阅片的条件 -->
|
||||||
<el-form-item
|
<el-form-item :label-width="'280px'" :label="$t('trials:adRules:title:judgeTypeEnum')" style="width: 95%">
|
||||||
:label-width="'280px'"
|
<el-radio-group v-model="QuestionList[index].JudgeType" @input="(val) => JudgeTypeChange(val, index)">
|
||||||
:label="$t('trials:adRules:title:judgeTypeEnum')"
|
|
||||||
style="width: 95%"
|
|
||||||
>
|
|
||||||
<el-radio-group
|
|
||||||
v-model="QuestionList[index].JudgeType"
|
|
||||||
@input="(val) => JudgeTypeChange(val, index)"
|
|
||||||
>
|
|
||||||
<template v-for="item of $d.JudgeTypeEnum">
|
<template v-for="item of $d.JudgeTypeEnum">
|
||||||
<el-radio
|
<el-radio style="margin-bottom: 5px" :key="item.id" :disabled="OtherInfo.IsSign ||
|
||||||
style="margin-bottom: 5px"
|
|
||||||
:key="item.id"
|
|
||||||
:disabled="
|
|
||||||
OtherInfo.IsSign ||
|
|
||||||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
||||||
"
|
" :label="item.value" v-if="
|
||||||
:label="item.value"
|
|
||||||
v-if="
|
|
||||||
item.value < 4 ||
|
item.value < 4 ||
|
||||||
(item.value > 3 &&
|
(item.value > 3 &&
|
||||||
(QuestionList[index].Type === 'number' ||
|
(QuestionList[index].Type === 'number' ||
|
||||||
QuestionList[index].Type === 'calculation'))
|
QuestionList[index].Type === 'calculation'))
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</el-radio>
|
</el-radio>
|
||||||
</template>
|
</template>
|
||||||
</el-radio-group>
|
</el-radio-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="QuestionList[index].JudgeType === 3" style="text-align: right; margin: 10px 0">
|
||||||
v-if="QuestionList[index].JudgeType === 3"
|
|
||||||
style="text-align: right; margin: 10px 0"
|
|
||||||
>
|
|
||||||
<!-- 添加规则 -->
|
<!-- 添加规则 -->
|
||||||
<el-button
|
<el-button v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']" size="mini" type="primary"
|
||||||
v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
:disabled="OtherInfo.IsSign" @click="addGroup(index, null)">{{ $t('trials:adRules:button:addRule')
|
||||||
size="mini"
|
}}</el-button>
|
||||||
type="primary"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
@click="addGroup(index, null)"
|
|
||||||
>{{ $t('trials:adRules:button:addRule') }}</el-button
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<el-table
|
<el-table v-if="QuestionList[index].JudgeType === 3" v-loading="loading"
|
||||||
v-if="QuestionList[index].JudgeType === 3"
|
:data="QuestionList[index].AnswerGroupList" border stripe>
|
||||||
v-loading="loading"
|
|
||||||
:data="QuestionList[index].AnswerGroupList"
|
|
||||||
border
|
|
||||||
stripe
|
|
||||||
>
|
|
||||||
<!-- 序号 -->
|
<!-- 序号 -->
|
||||||
<el-table-column
|
<el-table-column prop="AnswerGroupA" :label="$t('trials:adRules:title:order')" width="160">
|
||||||
prop="AnswerGroupA"
|
|
||||||
:label="$t('trials:adRules:title:order')"
|
|
||||||
width="160"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{ scope.$index + 1 }}
|
{{ scope.$index + 1 }}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 阅片人A -->
|
<!-- 阅片人A -->
|
||||||
<el-table-column
|
<el-table-column prop="AnswerGroupA" :label="$t('trials:adRules:title:answerGroupA')" min-width="100">
|
||||||
prop="AnswerGroupA"
|
|
||||||
:label="$t('trials:adRules:title:answerGroupA')"
|
|
||||||
min-width="100"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{
|
{{
|
||||||
QuestionList[index].QuestionGenre === 3
|
QuestionList[index].QuestionGenre === 3
|
||||||
|
|
@ -132,11 +72,7 @@
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<!-- 阅片人B -->
|
<!-- 阅片人B -->
|
||||||
<el-table-column
|
<el-table-column prop="AnswerGroupB" :label="$t('trials:adRules:title:answerGroupB')" min-width="100">
|
||||||
prop="AnswerGroupB"
|
|
||||||
:label="$t('trials:adRules:title:answerGroupB')"
|
|
||||||
min-width="100"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
{{
|
{{
|
||||||
QuestionList[index].QuestionGenre === 3
|
QuestionList[index].QuestionGenre === 3
|
||||||
|
|
@ -147,83 +83,48 @@
|
||||||
}}
|
}}
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column
|
<el-table-column prop="AnswerGroupB" :label="$t('common:action:action')" min-width="80">
|
||||||
prop="AnswerGroupB"
|
|
||||||
:label="$t('common:action:action')"
|
|
||||||
min-width="80"
|
|
||||||
>
|
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<!-- 编辑 -->
|
<!-- 编辑 -->
|
||||||
<el-button
|
<el-button icon="el-icon-edit" circle :title="$t('common:button:edit')" size="mini"
|
||||||
icon="el-icon-edit"
|
:disabled="OtherInfo.IsSign" @click="addGroup(index, scope.$index)" />
|
||||||
circle
|
|
||||||
:title="$t('common:button:edit')"
|
|
||||||
size="mini"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
@click="addGroup(index, scope.$index)"
|
|
||||||
/>
|
|
||||||
<!-- 删除 -->
|
<!-- 删除 -->
|
||||||
<el-button
|
<el-button icon="el-icon-delete" circle :title="$t('common:button:delete')" size="mini"
|
||||||
icon="el-icon-delete"
|
:disabled="OtherInfo.IsSign" @click="tagClose(index, scope.$index)" />
|
||||||
circle
|
|
||||||
:title="$t('common:button:delete')"
|
|
||||||
size="mini"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
@click="tagClose(index, scope.$index)"
|
|
||||||
/>
|
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
<div v-if="QuestionList[index].JudgeType === 2">
|
<div v-if="QuestionList[index].JudgeType === 2">
|
||||||
<div
|
<div style="
|
||||||
style="
|
|
||||||
background: #f6f6f6;
|
background: #f6f6f6;
|
||||||
border-radius: 20px;
|
border-radius: 20px;
|
||||||
padding: 15px 20px;
|
padding: 15px 20px;
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
"
|
">
|
||||||
>
|
<el-checkbox-group v-if="QuestionList[index].QuestionGenre === 3" v-model="QuestionList[index].grouping">
|
||||||
<el-checkbox-group
|
|
||||||
v-if="QuestionList[index].QuestionGenre === 3"
|
|
||||||
v-model="QuestionList[index].grouping"
|
|
||||||
>
|
|
||||||
<template v-for="item of $d[QuestionList[index].DictionaryCode]">
|
<template v-for="item of $d[QuestionList[index].DictionaryCode]">
|
||||||
<el-checkbox
|
<el-checkbox v-if="item.value !== -1" :key="item.id" :disabled="OtherInfo.IsSign" :label="item.value">{{
|
||||||
v-if="item.value !== -1"
|
item.label }}</el-checkbox>
|
||||||
:key="item.id"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
:label="item.value"
|
|
||||||
>{{ item.label }}</el-checkbox
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
<el-checkbox-group v-else v-model="QuestionList[index].grouping">
|
<el-checkbox-group v-else v-model="QuestionList[index].grouping">
|
||||||
<el-checkbox
|
<el-checkbox v-for="item of item.TypeValue.split('|')" :key="item" :disabled="OtherInfo.IsSign"
|
||||||
v-for="item of item.TypeValue.split('|')"
|
:label="item">{{
|
||||||
:key="item"
|
item }}</el-checkbox>
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
:label="item"
|
|
||||||
>{{ item }}</el-checkbox
|
|
||||||
>
|
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
<div style="margin-top: 20px">
|
<div style="margin-top: 20px">
|
||||||
<!-- 当前选择答案分组: -->
|
<!-- 当前选择答案分组: -->
|
||||||
{{ $t('trials:adRules:title:selectAnswerGroup') }}
|
{{ $t('trials:adRules:title:selectAnswerGroup') }}
|
||||||
<el-tag
|
<el-tag v-if="
|
||||||
v-if="
|
|
||||||
QuestionList[index].grouping.length > 0 &&
|
QuestionList[index].grouping.length > 0 &&
|
||||||
QuestionList[index].QuestionGenre !== 3
|
QuestionList[index].QuestionGenre !== 3
|
||||||
"
|
">{{
|
||||||
>{{
|
|
||||||
QuestionList[index].grouping.toString().replaceAll(',', '|')
|
QuestionList[index].grouping.toString().replaceAll(',', '|')
|
||||||
}}</el-tag
|
}}</el-tag>
|
||||||
>
|
<el-tag v-if="
|
||||||
<el-tag
|
|
||||||
v-if="
|
|
||||||
QuestionList[index].grouping.length > 0 &&
|
QuestionList[index].grouping.length > 0 &&
|
||||||
QuestionList[index].QuestionGenre === 3
|
QuestionList[index].QuestionGenre === 3
|
||||||
"
|
">{{
|
||||||
>{{
|
|
||||||
QuestionList[index].grouping
|
QuestionList[index].grouping
|
||||||
.map(
|
.map(
|
||||||
(v) =>
|
(v) =>
|
||||||
|
|
@ -233,54 +134,31 @@
|
||||||
)
|
)
|
||||||
.toString()
|
.toString()
|
||||||
.replaceAll(',', '|')
|
.replaceAll(',', '|')
|
||||||
}}</el-tag
|
}}</el-tag>
|
||||||
>
|
<el-button size="mini" type="primary" :disabled="OtherInfo.IsSign" @click="addGroup2(index)">
|
||||||
<el-button
|
|
||||||
size="mini"
|
|
||||||
type="primary"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
@click="addGroup2(index)"
|
|
||||||
>
|
|
||||||
<!-- 添加分组 -->
|
<!-- 添加分组 -->
|
||||||
{{ $t('trials:adRules:title:addGroup') }}
|
{{ $t('trials:adRules:title:addGroup') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="QuestionList[index].QuestionGenre !== 3" style="margin-top: 20px">
|
||||||
v-if="QuestionList[index].QuestionGenre !== 3"
|
|
||||||
style="margin-top: 20px"
|
|
||||||
>
|
|
||||||
{{ $t('trials:adRules:title:group') }}
|
{{ $t('trials:adRules:title:group') }}
|
||||||
<el-tag
|
<el-tag v-for="itemA of QuestionList[index].AnswerGroup2List" :key="itemA" closable
|
||||||
v-for="itemA of QuestionList[index].AnswerGroup2List"
|
style="margin-right: 10px" @close="
|
||||||
:key="itemA"
|
|
||||||
closable
|
|
||||||
style="margin-right: 10px"
|
|
||||||
@close="
|
|
||||||
() => {
|
() => {
|
||||||
return tagClose2(index, indexA)
|
return tagClose2(index, indexA)
|
||||||
}
|
}
|
||||||
"
|
">{{ itemA }}</el-tag>
|
||||||
>{{ itemA }}</el-tag
|
|
||||||
>
|
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="QuestionList[index].QuestionGenre === 3" style="margin-top: 20px">
|
||||||
v-if="QuestionList[index].QuestionGenre === 3"
|
|
||||||
style="margin-top: 20px"
|
|
||||||
>
|
|
||||||
<!-- 分组: -->
|
<!-- 分组: -->
|
||||||
{{ $t('trials:adRules:title:group') }}
|
{{ $t('trials:adRules:title:group') }}
|
||||||
<el-tag
|
<el-tag v-for="itemA of QuestionList[index].AnswerGroup2List" :key="itemA" closable
|
||||||
v-for="itemA of QuestionList[index].AnswerGroup2List"
|
style="margin-right: 10px" @close="
|
||||||
:key="itemA"
|
|
||||||
closable
|
|
||||||
style="margin-right: 10px"
|
|
||||||
@close="
|
|
||||||
() => {
|
() => {
|
||||||
return tagClose2(index, indexA)
|
return tagClose2(index, indexA)
|
||||||
}
|
}
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{
|
{{
|
||||||
itemA
|
itemA
|
||||||
.split('|')
|
.split('|')
|
||||||
|
|
@ -292,58 +170,31 @@
|
||||||
</el-tag>
|
</el-tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div v-if="
|
||||||
v-if="
|
|
||||||
QuestionList[index].JudgeType === 4 ||
|
QuestionList[index].JudgeType === 4 ||
|
||||||
QuestionList[index].JudgeType === 5
|
QuestionList[index].JudgeType === 5
|
||||||
"
|
">
|
||||||
>
|
<el-form :inline="true" :model="QuestionList[index]" class="demo-form-inline" :ref="'JudgeDifferenceValue' + QuestionList[index].JudgeType + index
|
||||||
<el-form
|
" :rules="JudgeDifferenceValueQRules">
|
||||||
:inline="true"
|
<el-form-item :label="$t(
|
||||||
:model="QuestionList[index]"
|
|
||||||
class="demo-form-inline"
|
|
||||||
:ref="
|
|
||||||
'JudgeDifferenceValue' + QuestionList[index].JudgeType + index
|
|
||||||
"
|
|
||||||
:rules="JudgeDifferenceValueQRules"
|
|
||||||
>
|
|
||||||
<el-form-item
|
|
||||||
:label="
|
|
||||||
$t(
|
|
||||||
`trials:trials-panel:setting:reading-unit:JudgeDifferenceType`
|
`trials:trials-panel:setting:reading-unit:JudgeDifferenceType`
|
||||||
)
|
)
|
||||||
"
|
" prop="JudgeDifferenceType">
|
||||||
prop="JudgeDifferenceType"
|
<el-select v-model="QuestionList[index].JudgeDifferenceType" placeholder="请选择"
|
||||||
>
|
:disabled="OtherInfo.IsSign">
|
||||||
<el-select
|
<el-option v-for="item of $d.JudgeDifferenceType" :key="item.id" :label="item.label"
|
||||||
v-model="QuestionList[index].JudgeDifferenceType"
|
:value="item.value">
|
||||||
placeholder="请选择"
|
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
>
|
|
||||||
<el-option
|
|
||||||
v-for="item of $d.JudgeDifferenceType"
|
|
||||||
:key="item.id"
|
|
||||||
:label="item.label"
|
|
||||||
:value="item.value"
|
|
||||||
>
|
|
||||||
</el-option>
|
</el-option>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item
|
<el-form-item :label="$t(
|
||||||
:label="
|
|
||||||
$t(
|
|
||||||
`trials:trials-panel:setting:reading-unit:JudgeDifferenceValue${QuestionList[index].JudgeType}`
|
`trials:trials-panel:setting:reading-unit:JudgeDifferenceValue${QuestionList[index].JudgeType}`
|
||||||
)
|
)
|
||||||
"
|
" prop="JudgeDifferenceValue">
|
||||||
prop="JudgeDifferenceValue"
|
|
||||||
>
|
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<el-input
|
<el-input v-model="QuestionList[index].JudgeDifferenceValue" clearable
|
||||||
v-model="QuestionList[index].JudgeDifferenceValue"
|
:disabled="OtherInfo.IsSign"></el-input>
|
||||||
clearable
|
<span style="margin-left: 10px" v-if="QuestionList[index].JudgeType !== 5">{{
|
||||||
:disabled="OtherInfo.IsSign"
|
|
||||||
></el-input>
|
|
||||||
<span style="margin-left: 10px">{{
|
|
||||||
$fd('ValueUnit', QuestionList[index].Unit)
|
$fd('ValueUnit', QuestionList[index].Unit)
|
||||||
}}</span>
|
}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -355,124 +206,62 @@
|
||||||
<!-- </el-tab-pane>-->
|
<!-- </el-tab-pane>-->
|
||||||
<!-- </el-tabs>-->
|
<!-- </el-tabs>-->
|
||||||
<!-- 选择答案 -->
|
<!-- 选择答案 -->
|
||||||
<el-dialog
|
<el-dialog v-if="QuestionVisible" :title="$t('trials:adRules:title:selectAnswer')" :visible.sync="QuestionVisible"
|
||||||
v-if="QuestionVisible"
|
width="800px" :close-on-click-modal="false" custom-class="base-dialog-wrapper" append-to-body>
|
||||||
:title="$t('trials:adRules:title:selectAnswer')"
|
|
||||||
:visible.sync="QuestionVisible"
|
|
||||||
width="800px"
|
|
||||||
:close-on-click-modal="false"
|
|
||||||
custom-class="base-dialog-wrapper"
|
|
||||||
append-to-body
|
|
||||||
>
|
|
||||||
<div class="base-dialog-body">
|
<div class="base-dialog-body">
|
||||||
<!-- 阅片人A -->
|
<!-- 阅片人A -->
|
||||||
<el-form-item
|
<el-form-item label-width="110px" :label="$t('trials:adRules:title:answerGroupA')">
|
||||||
label-width="110px"
|
|
||||||
:label="$t('trials:adRules:title:answerGroupA')"
|
|
||||||
>
|
|
||||||
<el-checkbox-group v-model="QuestionList[selectIndex].groupingA">
|
<el-checkbox-group v-model="QuestionList[selectIndex].groupingA">
|
||||||
<template
|
<template v-for="item of QuestionList[selectIndex].TypeValue.split('|')">
|
||||||
v-for="item of QuestionList[selectIndex].TypeValue.split('|')"
|
<el-checkbox v-if="QuestionList[selectIndex].QuestionGenre !== 3" :key="item" :label="item" :disabled="QuestionList[selectIndex].groupingB.length
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-if="QuestionList[selectIndex].QuestionGenre !== 3"
|
|
||||||
:key="item"
|
|
||||||
:label="item"
|
|
||||||
:disabled="
|
|
||||||
QuestionList[selectIndex].groupingB.length
|
|
||||||
? ~QuestionList[selectIndex].groupingB.indexOf(item)
|
? ~QuestionList[selectIndex].groupingB.indexOf(item)
|
||||||
: false
|
: false
|
||||||
"
|
">{{ item }}</el-checkbox>
|
||||||
>{{ item }}</el-checkbox
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template v-for="item of $d[QuestionList[selectIndex].DictionaryCode]">
|
||||||
v-for="item of $d[QuestionList[selectIndex].DictionaryCode]"
|
<el-checkbox v-if="
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-if="
|
|
||||||
QuestionList[selectIndex].QuestionGenre === 3 &&
|
QuestionList[selectIndex].QuestionGenre === 3 &&
|
||||||
item.value !== -1
|
item.value !== -1
|
||||||
"
|
" :key="item.id" :label="item.value" :disabled="QuestionList[selectIndex].groupingB.length
|
||||||
:key="item.id"
|
|
||||||
:label="item.value"
|
|
||||||
:disabled="
|
|
||||||
QuestionList[selectIndex].groupingB.length
|
|
||||||
? ~QuestionList[selectIndex].groupingB.indexOf(item.value)
|
? ~QuestionList[selectIndex].groupingB.indexOf(item.value)
|
||||||
: false
|
: false
|
||||||
"
|
">{{ item.label }}</el-checkbox>
|
||||||
>{{ item.label }}</el-checkbox
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<!-- 阅片人B -->
|
<!-- 阅片人B -->
|
||||||
<el-form-item
|
<el-form-item label-width="110px" :label="$t('trials:adRules:title:answerGroupB')">
|
||||||
label-width="110px"
|
|
||||||
:label="$t('trials:adRules:title:answerGroupB')"
|
|
||||||
>
|
|
||||||
<el-checkbox-group v-model="QuestionList[selectIndex].groupingB">
|
<el-checkbox-group v-model="QuestionList[selectIndex].groupingB">
|
||||||
<template
|
<template v-for="item of QuestionList[selectIndex].TypeValue.split('|')">
|
||||||
v-for="item of QuestionList[selectIndex].TypeValue.split('|')"
|
<el-checkbox v-if="QuestionList[selectIndex].QuestionGenre !== 3" :key="item" :label="item" :disabled="QuestionList[selectIndex].groupingA.length
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-if="QuestionList[selectIndex].QuestionGenre !== 3"
|
|
||||||
:key="item"
|
|
||||||
:label="item"
|
|
||||||
:disabled="
|
|
||||||
QuestionList[selectIndex].groupingA.length
|
|
||||||
? ~QuestionList[selectIndex].groupingA.indexOf(item)
|
? ~QuestionList[selectIndex].groupingA.indexOf(item)
|
||||||
: false
|
: false
|
||||||
"
|
">{{ item }}</el-checkbox>
|
||||||
>{{ item }}</el-checkbox
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
<template
|
<template v-for="item of $d[QuestionList[selectIndex].DictionaryCode]">
|
||||||
v-for="item of $d[QuestionList[selectIndex].DictionaryCode]"
|
<el-checkbox v-if="
|
||||||
>
|
|
||||||
<el-checkbox
|
|
||||||
v-if="
|
|
||||||
QuestionList[selectIndex].QuestionGenre === 3 &&
|
QuestionList[selectIndex].QuestionGenre === 3 &&
|
||||||
item.value !== -1
|
item.value !== -1
|
||||||
"
|
" :key="item.id" :label="item.value" :disabled="QuestionList[selectIndex].groupingA.length
|
||||||
:key="item.id"
|
|
||||||
:label="item.value"
|
|
||||||
:disabled="
|
|
||||||
QuestionList[selectIndex].groupingA.length
|
|
||||||
? ~QuestionList[selectIndex].groupingA.indexOf(item.value)
|
? ~QuestionList[selectIndex].groupingA.indexOf(item.value)
|
||||||
: false
|
: false
|
||||||
"
|
">{{ item.label }}</el-checkbox>
|
||||||
>{{ item.label }}</el-checkbox
|
|
||||||
>
|
|
||||||
</template>
|
</template>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
||||||
class="base-dialog-footer"
|
|
||||||
style="text-align: right; margin-top: 10px"
|
|
||||||
>
|
|
||||||
<!-- 取消 -->
|
<!-- 取消 -->
|
||||||
<el-button
|
<el-button v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']" :disabled="btnLoading" size="small"
|
||||||
v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
type="primary" @click="
|
||||||
:disabled="btnLoading"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="
|
|
||||||
QuestionVisible = false
|
QuestionVisible = false
|
||||||
$set(QuestionList[selectIndex], 'groupingA', [])
|
$set(QuestionList[selectIndex], 'groupingA', [])
|
||||||
$set(QuestionList[selectIndex], 'groupingB', [])
|
$set(QuestionList[selectIndex], 'groupingB', [])
|
||||||
"
|
">
|
||||||
>
|
|
||||||
{{ $t('common:button:cancel') }}
|
{{ $t('common:button:cancel') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button
|
<el-button v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']" :disabled="btnLoading" size="small"
|
||||||
v-hasPermi="['trials:trials-panel:setting:reading-unit:edit']"
|
type="primary" @click="save">
|
||||||
:disabled="btnLoading"
|
|
||||||
size="small"
|
|
||||||
type="primary"
|
|
||||||
@click="save"
|
|
||||||
>
|
|
||||||
{{ $t('common:button:save') }}
|
{{ $t('common:button:save') }}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -34,13 +34,22 @@
|
||||||
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1"
|
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1"
|
||||||
:label="$t('trials:readingUnit:readingRules:title:measureTool')">
|
:label="$t('trials:readingUnit:readingRules:title:measureTool')">
|
||||||
<el-checkbox-group v-model="form.ReadingToolList" :disabled="isConfirm ||
|
<el-checkbox-group v-model="form.ReadingToolList" :disabled="isConfirm ||
|
||||||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])" @change="handleReadingToolListChange">
|
||||||
">
|
|
||||||
<el-checkbox v-for="tool in tools" :key="tool.toolName" :label="tool.toolName" name="ReadingToolList">
|
<el-checkbox v-for="tool in tools" :key="tool.toolName" :label="tool.toolName" name="ReadingToolList">
|
||||||
{{ $t(`${tool.i18nKey}`) }}
|
{{ $t(`${tool.i18nKey}`) }}
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- 定圆工具半径 -->
|
||||||
|
<el-form-item v-if="form.ReadingToolList.includes('FixedRadiusCircleROI')"
|
||||||
|
:label="$t('trials:readingUnit:readingRules:title:circleRadius')" prop="CircleRadius">
|
||||||
|
<el-input v-model="form.CircleRadius" @input="(val) => handleNumberInput(val, 'CircleRadius')" clearable
|
||||||
|
:disabled="isConfirm ||
|
||||||
|
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
||||||
|
">
|
||||||
|
<template slot="append">mm</template>
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
<!--分割工具 && (form.ReadingTool === 0 || form.ReadingTool === 1 || form.ReadingTool === 2)-->
|
<!--分割工具 && (form.ReadingTool === 0 || form.ReadingTool === 1 || form.ReadingTool === 2)-->
|
||||||
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1 && form.ReadingTool === 3"
|
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1 && form.ReadingTool === 3"
|
||||||
:label="$t('trials:readingUnit:readingRules:title:segmentTool')">
|
:label="$t('trials:readingUnit:readingRules:title:segmentTool')">
|
||||||
|
|
@ -52,6 +61,22 @@
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
<!-- 分割组名 -->
|
||||||
|
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1 && form.ReadingTool === 3"
|
||||||
|
:label="$t('trials:readingUnit:readingRules:title:segmentations')" prop="DefaultSegmentName.SegmentationName">
|
||||||
|
<el-input v-model="form.DefaultSegmentName.SegmentationName" :disabled="isConfirm ||
|
||||||
|
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])" style="width: 80%">
|
||||||
|
</el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 分割片段 -->
|
||||||
|
<el-form-item v-if="CriterionType === 0 && form.ReadingVersionEnum === 1 && form.ReadingTool === 3"
|
||||||
|
:label="$t('trials:readingUnit:readingRules:title:segment')" prop="DefaultSegmentName.SegmentNameList">
|
||||||
|
<el-input v-model="form.SegmentNameListStr" style="width: 80%" disabled>
|
||||||
|
</el-input>
|
||||||
|
<el-button :disabled="isConfirm ||
|
||||||
|
!hasPermi(['trials:trials-panel:setting:reading-unit:edit'])
|
||||||
|
" icon="el-icon-plus" circle @click="segmentVisible = true" />
|
||||||
|
</el-form-item>
|
||||||
<!--检查类型筛选-->
|
<!--检查类型筛选-->
|
||||||
<el-form-item :label="$t('trials:processCfg:form:IsImageFilter')" prop="IsImageFilter">
|
<el-form-item :label="$t('trials:processCfg:form:IsImageFilter')" prop="IsImageFilter">
|
||||||
<el-radio-group v-model="form.IsImageFilter" @input="IsImageFilterChange" :disabled="isConfirm ||
|
<el-radio-group v-model="form.IsImageFilter" @input="IsImageFilterChange" :disabled="isConfirm ||
|
||||||
|
|
@ -392,6 +417,35 @@
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
<attachmentPreview :visible.sync="perview_visible" :isView="true" :isExternal="true" :ExternalList="ExternalList"
|
<attachmentPreview :visible.sync="perview_visible" :isView="true" :isExternal="true" :ExternalList="ExternalList"
|
||||||
v-if="perview_visible" />
|
v-if="perview_visible" />
|
||||||
|
<!-- 分割段编辑 -->
|
||||||
|
<el-dialog v-if="segmentVisible" :visible.sync="segmentVisible" :close-on-click-modal="false" width="600px"
|
||||||
|
:title="$t('trials:trialCfg:dialogTitle:addSegment')" custom-class="base-dialog-wrapper">
|
||||||
|
<div class="base-dialog-body">
|
||||||
|
<el-button @click.stop="addSegment" style="margin-bottom: 5px;" type="primary" size="small">{{
|
||||||
|
$t('common:button:new') }}</el-button>
|
||||||
|
<el-table :data="SegmentNameList" border style="width: 100%" size="small">
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column prop="name" :label="$t('trials:trialCfg:table:segmentName')" show-overflow-tooltip />
|
||||||
|
<el-table-column :label="$t('common:action:action')" align="left" fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button circle icon="el-icon-top" :title="$t('dictionary:template:keyDocList:button:up')"
|
||||||
|
@click.stop="sortSegment(scope, 'up')" :disabled="scope.$index === 0" />
|
||||||
|
<el-button circle icon="el-icon-bottom" :title="$t('dictionary:template:keyDocList:button:down')"
|
||||||
|
@click.stop="sortSegment(scope, 'down')" :disabled="scope.$index === SegmentNameList.length - 1" />
|
||||||
|
<el-button circle icon="el-icon-edit-outline" :title="$t('dictionary:template:keyDocList:button:update')"
|
||||||
|
@click.stop="updateSegment(scope)" />
|
||||||
|
<el-button circle icon="el-icon-delete" :title="$t('dictionary:template:keyDocList:button:del')"
|
||||||
|
@click.stop="delSegment(scope)" />
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
||||||
|
<el-button size="small" type="primary" @click="segmentVisible = false">
|
||||||
|
{{ $t('trials:trialCfg:button:confirmCfg') }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
|
|
@ -420,6 +474,7 @@ export default {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
segmentVisible: false,
|
||||||
perview_visible: false,
|
perview_visible: false,
|
||||||
ExternalList: [],
|
ExternalList: [],
|
||||||
keyDocVisible: false,
|
keyDocVisible: false,
|
||||||
|
|
@ -432,6 +487,11 @@ export default {
|
||||||
ReadingVersionEnum: null,
|
ReadingVersionEnum: null,
|
||||||
ReadingToolList: [],
|
ReadingToolList: [],
|
||||||
SegmentToolList: [],
|
SegmentToolList: [],
|
||||||
|
DefaultSegmentName: {
|
||||||
|
SegmentationName: null,
|
||||||
|
SegmentNameList: []
|
||||||
|
},
|
||||||
|
SegmentNameListStr: null,
|
||||||
ReadingTaskViewEnum: null,
|
ReadingTaskViewEnum: null,
|
||||||
IsImageLabeled: null,
|
IsImageLabeled: null,
|
||||||
IsReadingShowSubjectInfo: null,
|
IsReadingShowSubjectInfo: null,
|
||||||
|
|
@ -460,7 +520,8 @@ export default {
|
||||||
ImageUploadEnum: null,
|
ImageUploadEnum: null,
|
||||||
IsImageFilter: false,
|
IsImageFilter: false,
|
||||||
KeyFileListStr: '',
|
KeyFileListStr: '',
|
||||||
KeyFileList: []
|
KeyFileList: [],
|
||||||
|
CircleRadius: null
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
IsAutoCreate: [
|
IsAutoCreate: [
|
||||||
|
|
@ -596,6 +657,21 @@ export default {
|
||||||
trigger: ['blur', 'change'],
|
trigger: ['blur', 'change'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
'DefaultSegmentName.SegmentationName': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: this.$t('common:ruleMessage:specify'),
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'DefaultSegmentName.SegmentNameList': [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
type: 'array',
|
||||||
|
message: this.$t('common:ruleMessage:select'),
|
||||||
|
trigger: ['blur', 'change'],
|
||||||
|
},
|
||||||
|
],
|
||||||
CriterionModalitys: [
|
CriterionModalitys: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
|
|
@ -613,6 +689,10 @@ export default {
|
||||||
trigger: ['blur', 'change'],
|
trigger: ['blur', 'change'],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
CircleRadius: [
|
||||||
|
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'], },
|
||||||
|
{ pattern: /^(0|[1-9]\d*)(\.\d{1,2})?$/, message: '请输入正确的数值格式,最多两位小数', trigger: 'blur' }
|
||||||
|
]
|
||||||
// IsReadingTaskViewInOrder: [
|
// IsReadingTaskViewInOrder: [
|
||||||
// { required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
// { required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }
|
||||||
// ]
|
// ]
|
||||||
|
|
@ -642,6 +722,16 @@ export default {
|
||||||
isUSA() {
|
isUSA() {
|
||||||
return process.env.NODE_ENV === 'usa'
|
return process.env.NODE_ENV === 'usa'
|
||||||
},
|
},
|
||||||
|
SegmentNameList() {
|
||||||
|
let arr = []
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.forEach(item => {
|
||||||
|
let obj = {
|
||||||
|
name: item
|
||||||
|
}
|
||||||
|
arr.push(obj)
|
||||||
|
})
|
||||||
|
return arr
|
||||||
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
CriterionModalitys: {
|
CriterionModalitys: {
|
||||||
|
|
@ -652,6 +742,76 @@ export default {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
sortSegment(row, key) {
|
||||||
|
let index = row.$index
|
||||||
|
let name = row.row.name
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.splice(index, 1)
|
||||||
|
if (key === 'up') {
|
||||||
|
|
||||||
|
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.splice(index - 1, 0, name)
|
||||||
|
} else {
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.splice(index + 1, 0, name)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async updateSegment(row) {
|
||||||
|
let name = await this.customPrompt(row.row.name)
|
||||||
|
if (!name) return false
|
||||||
|
let index = row.$index
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.splice(index, 1, name)
|
||||||
|
this.form.SegmentNameListStr = this.form.DefaultSegmentName.SegmentNameList.join("|")
|
||||||
|
},
|
||||||
|
delSegment(row) {
|
||||||
|
console.log(row)
|
||||||
|
let index = row.$index
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.splice(index, 1)
|
||||||
|
this.form.SegmentNameListStr = this.form.DefaultSegmentName.SegmentNameList.join("|")
|
||||||
|
},
|
||||||
|
async addSegment() {
|
||||||
|
let name = await this.customPrompt()
|
||||||
|
if (!name) return false
|
||||||
|
this.form.DefaultSegmentName.SegmentNameList.push(name)
|
||||||
|
this.form.SegmentNameListStr = this.form.DefaultSegmentName.SegmentNameList.join("|")
|
||||||
|
},
|
||||||
|
async customPrompt(name = null) {
|
||||||
|
try {
|
||||||
|
const that = this
|
||||||
|
// 请输入标记名称
|
||||||
|
let message = !name ? this.$t('trials:reading:Segmentations:message:add') : this.$t('trials:reading:Segmentations:message:upate')
|
||||||
|
const { value } = await this.$prompt(message, '', {
|
||||||
|
showClose: false,
|
||||||
|
cancelButtonText: this.$t('common:button:cancel'),
|
||||||
|
confirmButtonText: this.$t('common:button:save'),
|
||||||
|
showCancelButton: true,
|
||||||
|
closeOnClickModal: false,
|
||||||
|
closeOnPressEscape: false,
|
||||||
|
inputValue: name,
|
||||||
|
inputValidator: (value) => {
|
||||||
|
if (!value) {
|
||||||
|
return that.$t("trials:reading:Segmentations:message:notName")
|
||||||
|
} else if (value === name) {
|
||||||
|
return true
|
||||||
|
} else if (that.form.DefaultSegmentName.SegmentNameList.includes(value)) {
|
||||||
|
return that.$t("trials:reading:Segmentations:message:nameIsHas")
|
||||||
|
} else {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeClose: (action, instance, done) => {
|
||||||
|
if (action === 'confirm') {
|
||||||
|
// const value = instance.inputValue
|
||||||
|
done()
|
||||||
|
} else {
|
||||||
|
done()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return value
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
async viewManual() {
|
async viewManual() {
|
||||||
try {
|
try {
|
||||||
if (this.form.KeyFileList.length <= 0) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:noImageManual"))
|
if (this.form.KeyFileList.length <= 0) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:noImageManual"))
|
||||||
|
|
@ -814,6 +974,7 @@ export default {
|
||||||
if (this.form.ReadingTool === 3) {
|
if (this.form.ReadingTool === 3) {
|
||||||
this.segmentTools = [...config.customizeStandardsSegmentDicom]
|
this.segmentTools = [...config.customizeStandardsSegmentDicom]
|
||||||
}
|
}
|
||||||
|
this.form.SegmentNameListStr = res.Result.DefaultSegmentName.SegmentNameList.join(",")
|
||||||
}
|
}
|
||||||
this.CriterionModalitys = this.form.CriterionModalitys
|
this.CriterionModalitys = this.form.CriterionModalitys
|
||||||
? this.form.CriterionModalitys.split('|')
|
? this.form.CriterionModalitys.split('|')
|
||||||
|
|
@ -900,6 +1061,37 @@ export default {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
handleReadingToolListChange(v) {
|
||||||
|
if (!v.includes('FixedRadiusCircleROI')) {
|
||||||
|
this.form.CircleRadius = null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleNumberInput(value, field) {
|
||||||
|
if (!value) {
|
||||||
|
this.form[field] = ''
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let val = value.toString()
|
||||||
|
|
||||||
|
// 1. 清除“数字”和“.”以外的字符
|
||||||
|
val = val.replace(/[^\d.]/g, '')
|
||||||
|
// 2. 保证第一个字符不能是“.”
|
||||||
|
val = val.replace(/^\./g, '')
|
||||||
|
// 3. 保证不能连续输入多个“.”,只保留第一个
|
||||||
|
val = val.replace(/\.{2,}/g, '.')
|
||||||
|
val = val.replace('.', '$#$').replace(/\./g, '').replace('$#$', '.')
|
||||||
|
// 4. 限制只能输入两位小数
|
||||||
|
val = val.replace(/^(\-)*(\d+)\.(\d{2}).*$/, '$1$2.$3')
|
||||||
|
// 5. 处理前导零(例如输入 01 自动变成 1)
|
||||||
|
if (val.length > 1 && val[0] === '0' && val[1] !== '.') {
|
||||||
|
val = val.replace(/^0+/, '')
|
||||||
|
if (val === '') val = '0'
|
||||||
|
}
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.ruleForm[field] = val
|
||||||
|
});
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,24 @@
|
||||||
<!-- 配置信息表单 -->
|
<!-- 配置信息表单 -->
|
||||||
<el-form ref="processConfigForm" v-loading="loading" :model="form" label-width="300px" style="width: 800px"
|
<el-form ref="processConfigForm" v-loading="loading" :model="form" label-width="300px" style="width: 800px"
|
||||||
:rules="rules" size="small">
|
:rules="rules" size="small">
|
||||||
|
<!-- 数据存储 -->
|
||||||
|
<el-form-item
|
||||||
|
:label="$t('trials:processCfg:form:trialDataStoreType')"
|
||||||
|
prop="TrialDataStoreType"
|
||||||
|
>
|
||||||
|
<el-radio-group
|
||||||
|
v-model="form.TrialDataStoreType"
|
||||||
|
:disabled="form.IsTrialProcessConfirmed && !isEdit"
|
||||||
|
>
|
||||||
|
<el-radio
|
||||||
|
v-for="item of $d.TrialDataStoreType"
|
||||||
|
:key="item.id"
|
||||||
|
:label="item.value"
|
||||||
|
>
|
||||||
|
{{ item.label }}
|
||||||
|
</el-radio>
|
||||||
|
</el-radio-group>
|
||||||
|
</el-form-item>
|
||||||
<!-- 阅片方式 -->
|
<!-- 阅片方式 -->
|
||||||
<el-form-item :label="$t('trials:processCfg:form:readingMode')" prop="ReadingMode">
|
<el-form-item :label="$t('trials:processCfg:form:readingMode')" prop="ReadingMode">
|
||||||
<el-radio-group v-model="form.ReadingMode" :disabled="form.IsTrialProcessConfirmed && !isEdit">
|
<el-radio-group v-model="form.ReadingMode" :disabled="form.IsTrialProcessConfirmed && !isEdit">
|
||||||
|
|
@ -78,6 +96,7 @@
|
||||||
</el-checkbox>
|
</el-checkbox>
|
||||||
</el-checkbox-group>
|
</el-checkbox-group>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|
||||||
<!-- 修约小数位数 -->
|
<!-- 修约小数位数 -->
|
||||||
<!-- <el-form-item
|
<!-- <el-form-item
|
||||||
:label="$t('trials:processCfg:form:digitPlaces')"
|
:label="$t('trials:processCfg:form:digitPlaces')"
|
||||||
|
|
@ -724,6 +743,7 @@ export default {
|
||||||
VUE_IS_TEST: process.env.VUE_APP_IS_TEST,
|
VUE_IS_TEST: process.env.VUE_APP_IS_TEST,
|
||||||
form: {
|
form: {
|
||||||
TrialId: '',
|
TrialId: '',
|
||||||
|
TrialDataStoreType: 0,
|
||||||
ClinicalInformationTransmissionEnum: 1,
|
ClinicalInformationTransmissionEnum: 1,
|
||||||
ClinicalDataSetNames: [],
|
ClinicalDataSetNames: [],
|
||||||
ClinicalDataTrialSetIds: [],
|
ClinicalDataTrialSetIds: [],
|
||||||
|
|
@ -750,6 +770,13 @@ export default {
|
||||||
TrialCriterionIdEnums: [],
|
TrialCriterionIdEnums: [],
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
|
TrialDataStoreType: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: this.$t('common:ruleMessage:select'),
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
],
|
||||||
ClinicalDataSetNamesStr: [
|
ClinicalDataSetNamesStr: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
|
|
@ -1005,6 +1032,11 @@ export default {
|
||||||
// initialCriterions.push(this.$fd('ReadingStandard', id, 'id'))
|
// initialCriterions.push(this.$fd('ReadingStandard', id, 'id'))
|
||||||
// })
|
// })
|
||||||
this.confirmData = [
|
this.confirmData = [
|
||||||
|
{
|
||||||
|
Name: this.$t('trials:processCfg:form:trialDataStoreType'), // 数据存储
|
||||||
|
NewVal: this.$fd('TrialDataStoreType', this.form.TrialDataStoreType),
|
||||||
|
OldVal: this.$fd('TrialDataStoreType', this.initialForm.TrialDataStoreType),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
Name: this.$t('trials:processCfg:form:readingMode'), // 阅片方式
|
Name: this.$t('trials:processCfg:form:readingMode'), // 阅片方式
|
||||||
NewVal: this.$fd('ReadingMode', this.form.ReadingMode),
|
NewVal: this.$fd('ReadingMode', this.form.ReadingMode),
|
||||||
|
|
|
||||||
|
|
@ -261,12 +261,23 @@ export default {
|
||||||
uploadFilesAndSave() {
|
uploadFilesAndSave() {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
this.form.AddFileList = []
|
this.form.AddFileList = []
|
||||||
|
let uploadBatchId = this.$guid()
|
||||||
for (var i = 0; i < this.pendingUploadList.length; ++i) {
|
for (var i = 0; i < this.pendingUploadList.length; ++i) {
|
||||||
// const file = await this.convertBase64ToBlob(this.pendingUploadList[i])
|
// const file = await this.convertBase64ToBlob(this.pendingUploadList[i])
|
||||||
const file = await this.fileToBlob(this.pendingUploadList[i])
|
const file = await this.fileToBlob(this.pendingUploadList[i])
|
||||||
const res = await this.OSSclient.put(
|
const res = await this.OSSclient.put(
|
||||||
`/${this.data.TrialId}/ClinicalData/${this.pendingUploadList[i].name}`,
|
`/${this.data.TrialId}/ClinicalData/${this.pendingUploadList[i].name}`,
|
||||||
file
|
file,
|
||||||
|
{
|
||||||
|
fileName: this.pendingUploadList[i].name,
|
||||||
|
fileSize: this.pendingUploadList[i].size,
|
||||||
|
fileType: this.pendingUploadList[i].type,
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 4,
|
||||||
|
trialId: this.data.TrialId,
|
||||||
|
subjectId: this.data.SubjectId,
|
||||||
|
subjectVisitId: this.data.SubjectVisitId
|
||||||
|
}
|
||||||
)
|
)
|
||||||
this.form.AddFileList.push({
|
this.form.AddFileList.push({
|
||||||
fileName: this.pendingUploadList[i].name,
|
fileName: this.pendingUploadList[i].name,
|
||||||
|
|
|
||||||
|
|
@ -551,6 +551,7 @@ export default {
|
||||||
IsVisit: this.data.IsVisit,
|
IsVisit: this.data.IsVisit,
|
||||||
SubjectId: this.data.SubjectId,
|
SubjectId: this.data.SubjectId,
|
||||||
IsBaseLine: this.data.IsBaseLine,
|
IsBaseLine: this.data.IsBaseLine,
|
||||||
|
SubjectVisitId: this.data.SubjectVisitId
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
this.addOrUpdateCD.title = this.$t('common:button:new')
|
this.addOrUpdateCD.title = this.$t('common:button:new')
|
||||||
|
|
@ -565,6 +566,7 @@ export default {
|
||||||
}
|
}
|
||||||
this.currentData.IsVisit = this.data.IsVisit
|
this.currentData.IsVisit = this.data.IsVisit
|
||||||
this.currentData.IsBaseLine = this.data.IsBaseLine
|
this.currentData.IsBaseLine = this.data.IsBaseLine
|
||||||
|
this.currentData.SubjectVisitId = this.data.SubjectVisitId
|
||||||
this.addOrUpdateCD.title = this.$t('common:button:edit')
|
this.addOrUpdateCD.title = this.$t('common:button:edit')
|
||||||
this.currentOption = [
|
this.currentOption = [
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -46,20 +46,49 @@ import {
|
||||||
getTrialCriterionList,
|
getTrialCriterionList,
|
||||||
getReportsChartSummary
|
getReportsChartSummary
|
||||||
} from '@/api/trials'
|
} from '@/api/trials'
|
||||||
let echarts = require('echarts/lib/echarts');
|
import * as echarts from 'echarts/core';
|
||||||
|
import { LineChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
// 内置数据转换器组件 (filter, sort)
|
||||||
|
TransformComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
// 标签自动布局、全局过渡动画等特性
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
LineChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
// let echarts = require('echarts/lib/echarts');
|
||||||
|
|
||||||
// 按需引入图表
|
// 按需引入图表
|
||||||
// require('echarts/lib/chart/bar');
|
// require('echarts/lib/chart/bar');
|
||||||
require('echarts/lib/chart/line');
|
// require('echarts/lib/chart/line');
|
||||||
// require('echarts/lib/chart/pie');
|
// require('echarts/lib/chart/pie');
|
||||||
// require('echarts/lib/chart/scatter');
|
// require('echarts/lib/chart/scatter');
|
||||||
|
|
||||||
// 按需引入组件
|
// 按需引入组件
|
||||||
require('echarts/lib/component/tooltip');
|
// require('echarts/lib/component/tooltip');
|
||||||
require('echarts/lib/component/title');
|
// require('echarts/lib/component/title');
|
||||||
require('echarts/lib/component/legend');
|
// require('echarts/lib/component/legend');
|
||||||
require('echarts/lib/component/grid');
|
// require('echarts/lib/component/grid');
|
||||||
require('echarts/lib/component/dataZoom');
|
// require('echarts/lib/component/dataZoom');
|
||||||
export default {
|
export default {
|
||||||
name: "SubjectChart",
|
name: "SubjectChart",
|
||||||
props: {
|
props: {
|
||||||
|
|
@ -259,12 +288,19 @@ export default {
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
},
|
},
|
||||||
|
grid: {
|
||||||
|
left: 30,
|
||||||
|
bottom: 30
|
||||||
|
},
|
||||||
xAxis: {
|
xAxis: {
|
||||||
data: obj.visitName,
|
data: obj.visitName,
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
name: obj.unit,
|
name: obj.unit,
|
||||||
type: 'value',
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
series: obj.series
|
series: obj.series
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,442 @@
|
||||||
|
<template>
|
||||||
|
<BaseContainer>
|
||||||
|
<template slot="search-container">
|
||||||
|
<el-form :inline="true">
|
||||||
|
<!-- 文件名称 -->
|
||||||
|
<el-form-item label="文件名称" prop="FileName">
|
||||||
|
<el-input v-model="searchData.FileName" size="small" clearable style="width: 120px" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 文件类型 -->
|
||||||
|
<el-form-item label="文件类型" prop="FileType">
|
||||||
|
<el-input v-model="searchData.FileType" size="small" clearable style="width: 120px" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 源区域 -->
|
||||||
|
<el-form-item label="源区域" prop="UploadRegion">
|
||||||
|
<el-select v-model="searchData.UploadRegion" style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in regionOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 源可用时间 -->
|
||||||
|
<el-form-item label="源可用时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="uploadTimeRange"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
@change="handleUploadtimeChange"
|
||||||
|
style="width: 300px"
|
||||||
|
type="datetimerange">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 目标区域 -->
|
||||||
|
<el-form-item label="目标区域" prop="TargetRegion">
|
||||||
|
<el-select v-model="searchData.TargetRegion" style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in regionOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 目标可用时间 -->
|
||||||
|
<el-form-item label="目标可用时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="SyncTimeRange"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
@change="handleSynctimeChange"
|
||||||
|
style="width: 300px"
|
||||||
|
type="datetimerange">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 优先级 -->
|
||||||
|
<el-form-item label="优先级">
|
||||||
|
<el-input v-model="searchData.Priority" clearable style="width: 120px"></el-input>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 是否同步完成 -->
|
||||||
|
<el-form-item label="是否同步完成" prop="IsSync">
|
||||||
|
<el-select v-model="searchData.IsSync" clearable style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:key="'IsSync' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</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-button type="primary" icon="el-icon-edit" :disabled="selectedRows.length === 0" @click="handleBatchEdit">
|
||||||
|
批量编辑
|
||||||
|
</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
<template slot="main-container">
|
||||||
|
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 70 }" height="100" :data="list"
|
||||||
|
class="table" @sort-change="handleSortByColumn" :default-sort="{ prop: 'CreateTime', order: 'descending' }" @selection-change="handleSelectionChange">
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column type="selection" width="50" :selectable="selectableRow"/>
|
||||||
|
<el-table-column label="文件名称" prop="FileName" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="文件大小" prop="FileSize" min-width="90" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ fileSizeFormatter(scope.row.FileSize) }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="文件类型" prop="FileType" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column label="源区域" prop="UploadRegion" min-width="60" show-overflow-tooltip sortable="custom" />
|
||||||
|
|
||||||
|
<el-table-column label="源可用时间" prop="CreateTime" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="路径" prop="Path" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="是否需要同步" prop="IsNeedSync" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.IsNeedSync" type="success">
|
||||||
|
{{ $fd('YesOrNo', scope.row.IsNeedSync) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="danger">
|
||||||
|
{{ $fd('YesOrNo', scope.row.IsNeedSync) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="目标区域" prop="TargetRegion" min-width="80" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="目标可用时间" prop="SyncFinishedTime" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="优先级" prop="Priority" min-width="60" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="是否同步完成" prop="IsSync" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.IsSync" type="success">
|
||||||
|
{{ $fd('YesOrNo', scope.row.IsSync) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="danger">
|
||||||
|
{{ $fd('YesOrNo', scope.row.IsSync) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="更新时间" prop="UpdateTime" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="操作" width="240" show-overflow-tooltip fixed="right">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="primary" size="mini" @click="handleOpenTaskTable(scope.row)">
|
||||||
|
详情
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="mini" :disabled="!scope.row.IsNeedSync || !scope.row.IsSync" @click="execute(scope.row)">
|
||||||
|
重新同步
|
||||||
|
</el-button>
|
||||||
|
<el-button type="primary" size="mini" :disabled="scope.row.IsSync" @click="handleEdit(scope.row)">
|
||||||
|
编辑
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</template>
|
||||||
|
<el-dialog v-if="editDialogVisible" title="编辑" :visible.sync="editDialogVisible" width="600px" :close-on-click-modal="false" append-to-body>
|
||||||
|
<el-form ref="editFormRef" :model="editForm" :rules="editRules" label-width="110px" v-loading="formLoading">
|
||||||
|
<el-form-item label="文件名称">
|
||||||
|
<el-input v-model="editForm.FileName" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="文件大小">
|
||||||
|
<el-input :value="fileSizeFormatter(editForm.FileSize)" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="文件类型">
|
||||||
|
<el-input v-model="editForm.FileType" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="源区域">
|
||||||
|
<el-input v-model="editForm.UploadRegion" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="目标区域">
|
||||||
|
<el-input v-model="editForm.TargetRegion" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否需要同步" prop="IsNeedSync">
|
||||||
|
<el-select v-model="editForm.IsNeedSync" style="width: 100%">
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:key="'IsNeedSync' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
|
||||||
|
<el-form-item label="更新时间">
|
||||||
|
<el-input v-model="editForm.UpdateTime" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="路径">
|
||||||
|
<el-input v-model="editForm.Path" type="textarea" :rows="2" disabled />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="优先级" prop="Priority">
|
||||||
|
<el-input-number v-model="editForm.Priority" :min="0" :controls="true" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="是否同步完成" prop="IsSync">
|
||||||
|
<el-select v-model="editForm.IsSync" style="width: 100%" disabled>
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:key="'IsSync' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="editDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleSaveEdit">保存</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
<el-dialog v-if="batchEditDialogVisible" title="批量编辑" :visible.sync="batchEditDialogVisible" width="300px" :close-on-click-modal="false" append-to-body>
|
||||||
|
<el-form ref="batchEditFormRef" :model="batchEditForm" :rules="batchEditRules" label-width="80px" v-loading="formLoading">
|
||||||
|
<el-form-item label="优先级" prop="Priority">
|
||||||
|
<el-input-number v-model="batchEditForm.Priority" :min="0" :controls="true" style="width: 100%" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="batchEditDialogVisible = false">取消</el-button>
|
||||||
|
<el-button type="primary" @click="handleSaveBatchEdit">保存</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog>
|
||||||
|
</BaseContainer>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { getFileUploadRecordList, addOrUpdateFileUploadRecord, batchAddSyncFileTask } from '@/api/file'
|
||||||
|
import BaseContainer from '@/components/BaseContainer'
|
||||||
|
import Pagination from '@/components/Pagination'
|
||||||
|
import moment from 'moment'
|
||||||
|
const searchDataDefault = () => {
|
||||||
|
return {
|
||||||
|
TrialId: '',
|
||||||
|
DataFileType: null,
|
||||||
|
SubjectCode: '',
|
||||||
|
VisitName: '',
|
||||||
|
StudyCode: '',
|
||||||
|
FileName: '',
|
||||||
|
UploadRegion: null,
|
||||||
|
TargetRegion: null,
|
||||||
|
IsSync: null,
|
||||||
|
UploadStartTime: null,
|
||||||
|
UploadEndTime: null,
|
||||||
|
SyncFinishedStartTime: null,
|
||||||
|
SyncFinishedEndTime: null,
|
||||||
|
Priority: null,
|
||||||
|
Asc: false,
|
||||||
|
SortField: 'UpdateTime',
|
||||||
|
PageIndex: 1,
|
||||||
|
PageSize: 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
name: 'FileList',
|
||||||
|
components: { BaseContainer, Pagination },
|
||||||
|
props: {
|
||||||
|
rowInfo: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
dataFileType: {
|
||||||
|
type: Number,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
moment,
|
||||||
|
searchData: searchDataDefault(),
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
loading: false,
|
||||||
|
uploadTimeRange: null,
|
||||||
|
SyncTimeRange: null,
|
||||||
|
regionOptions: [
|
||||||
|
{
|
||||||
|
value: 'CN',
|
||||||
|
label: 'CN'
|
||||||
|
}, {
|
||||||
|
value: 'US',
|
||||||
|
label: 'US'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
editDialogVisible: false,
|
||||||
|
editForm: {
|
||||||
|
// Priority: null,
|
||||||
|
// IsSync: null,
|
||||||
|
},
|
||||||
|
editRules: {
|
||||||
|
Priority: [{ required: true, message: '请输入', trigger: 'change' }],
|
||||||
|
IsSync: [{ required: true, message: '请选择', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
formLoading: false,
|
||||||
|
selectedRows: [],
|
||||||
|
batchEditDialogVisible: false,
|
||||||
|
batchEditForm: {
|
||||||
|
Priority: null,
|
||||||
|
},
|
||||||
|
batchEditRules: {
|
||||||
|
Priority: [{ required: true, message: '请输入', trigger: 'change' }],
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getList() {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
this.searchData.TrialId = this.$route.query.trialId
|
||||||
|
this.searchData.SubjectCode = this.rowInfo.SubjectCode
|
||||||
|
this.searchData.VisitName = this.rowInfo.VisitName
|
||||||
|
this.searchData.StudyCode = this.rowInfo.StudyCode
|
||||||
|
this.searchData.DataFileType = this.dataFileType
|
||||||
|
let res = await getFileUploadRecordList(this.searchData)
|
||||||
|
this.loading = false
|
||||||
|
this.list = res.Result.CurrentPageData
|
||||||
|
this.total = res.Result.TotalCount
|
||||||
|
} catch(e) {
|
||||||
|
this.loading = false
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleOpenTaskTable(row) {
|
||||||
|
this.$emit('openTaskTable', row)
|
||||||
|
},
|
||||||
|
handleEdit(row) {
|
||||||
|
this.editForm = {...row}
|
||||||
|
this.editDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.editFormRef) this.$refs.editFormRef.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async handleSaveEdit() {
|
||||||
|
try {
|
||||||
|
let valid = await this.$refs.editFormRef.validate()
|
||||||
|
if (!valid) return
|
||||||
|
this.formLoading = true
|
||||||
|
let res = await addOrUpdateFileUploadRecord(this.editForm)
|
||||||
|
this.formLoading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.editDialogVisible = false
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
this.formLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async execute(row) {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
let params = {
|
||||||
|
fileUploadRecordIdList: [row.Id]
|
||||||
|
}
|
||||||
|
let res = await batchAddSyncFileTask(params)
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.$message.success('执行成功!')
|
||||||
|
}
|
||||||
|
this.loading = false
|
||||||
|
this.getList()
|
||||||
|
} catch(e) {
|
||||||
|
this.loading = false
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
handleSelectionChange(rows) {
|
||||||
|
this.selectedRows = rows
|
||||||
|
},
|
||||||
|
selectableRow(row) {
|
||||||
|
return !row.IsSync
|
||||||
|
},
|
||||||
|
handleBatchEdit() {
|
||||||
|
if (!this.selectedRows.length) return
|
||||||
|
this.batchEditForm = {
|
||||||
|
Priority: null,
|
||||||
|
}
|
||||||
|
this.batchEditDialogVisible = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.batchEditFormRef) this.$refs.batchEditFormRef.clearValidate()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
async handleSaveBatchEdit() {
|
||||||
|
try {
|
||||||
|
let valid = await this.$refs.batchEditFormRef.validate()
|
||||||
|
if (!valid) return
|
||||||
|
this.formLoading = true
|
||||||
|
let params = {
|
||||||
|
fileUploadRecordIdList: this.selectedRows,
|
||||||
|
priority: this.editForm.Priority
|
||||||
|
}
|
||||||
|
let res = await batchAddSyncFileTask(params)
|
||||||
|
this.formLoading = false
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.batchEditDialogVisible = false
|
||||||
|
this.getList()
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
this.formLoading = false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fileSizeFormatter(size) {
|
||||||
|
if (!size) return
|
||||||
|
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
|
||||||
|
},
|
||||||
|
handleUploadtimeChange(val) {
|
||||||
|
if (val) {
|
||||||
|
this.searchData.UploadStartTime = val[0]
|
||||||
|
this.searchData.UploadEndTime = val[1]
|
||||||
|
} else {
|
||||||
|
this.searchData.UploadStartTime = ''
|
||||||
|
this.searchData.UploadEndTime = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSynctimeChange(val) {
|
||||||
|
if (val) {
|
||||||
|
this.searchData.SyncFinishedStartTime = val[0]
|
||||||
|
this.searchData.SyncFinishedEndTime = val[1]
|
||||||
|
} else {
|
||||||
|
this.searchData.SyncFinishedStartTime = ''
|
||||||
|
this.searchData.SyncFinishedEndTime = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSearch() {
|
||||||
|
this.searchData.PageIndex = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 重置列表查询
|
||||||
|
handleReset() {
|
||||||
|
this.uploadTimeRange = null
|
||||||
|
this.handleUploadtimeChange()
|
||||||
|
this.SyncTimeRange = null
|
||||||
|
this.handleSynctimeChange()
|
||||||
|
this.searchData = searchDataDefault()
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,351 @@
|
||||||
|
<template>
|
||||||
|
<BaseContainer>
|
||||||
|
<template slot="search-container">
|
||||||
|
<el-form :inline="true">
|
||||||
|
<!-- 受试者编号 -->
|
||||||
|
<el-form-item label="受试者编号" prop="SubjectCode">
|
||||||
|
<el-input v-model="searchData.SubjectCode" size="small" clearable style="width: 120px" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 访视名称 -->
|
||||||
|
<el-form-item label="访视名称">
|
||||||
|
<el-select v-model="searchData.VisitName" style="width: 140px" clearable>
|
||||||
|
<el-option v-for="(item, index) of visitPlanOptions" :key="index" :label="item.VisitName"
|
||||||
|
:value="item.VisitNum">
|
||||||
|
<span style="float: left">{{ item.VisitName }}</span>
|
||||||
|
</el-option>
|
||||||
|
<!-- <el-option key="Other" label="Out of Plan" value="1.11" /> -->
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 检查编号 -->
|
||||||
|
<el-form-item label="检查编号" prop="StudyCode">
|
||||||
|
<el-input v-model="searchData.StudyCode" size="small" clearable style="width: 120px" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 源区域 -->
|
||||||
|
<el-form-item label="源区域" prop="UploadRegion">
|
||||||
|
<el-select v-model="searchData.UploadRegion" style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in regionOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 源可用时间 -->
|
||||||
|
<!-- <el-form-item label="源可用时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="uploadTimeRange"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
@change="handleUploadtimeChange"
|
||||||
|
style="width: 250px"
|
||||||
|
type="datetimerange">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item> -->
|
||||||
|
<!-- 目标区域 -->
|
||||||
|
<el-form-item label="目标区域" prop="TargetRegion">
|
||||||
|
<el-select v-model="searchData.TargetRegion" style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item in regionOptions"
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value">
|
||||||
|
</el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 目标可用时间 -->
|
||||||
|
<!-- <el-form-item label="目标可用时间">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="SyncTimeRange"
|
||||||
|
:default-time="['00:00:00', '23:59:59']"
|
||||||
|
value-format="yyyy-MM-dd HH:mm:ss"
|
||||||
|
@change="handleSynctimeChange"
|
||||||
|
style="width: 250px"
|
||||||
|
type="datetimerange">
|
||||||
|
</el-date-picker>
|
||||||
|
</el-form-item> -->
|
||||||
|
<!-- 是否同步完成 -->
|
||||||
|
<el-form-item label="是否同步完成" prop="IsSync">
|
||||||
|
<el-select v-model="searchData.IsSync" clearable style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.YesOrNo"
|
||||||
|
:key="'IsSync' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</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-form>
|
||||||
|
</template>
|
||||||
|
<template slot="main-container">
|
||||||
|
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 60 }" height="100" :data="list"
|
||||||
|
class="table" @sort-change="handleSortByColumn" :default-sort="{ prop: 'CreateTime', order: 'descending' }">
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column label="受试者编号" prop="SubjectCode" min-width="90" show-overflow-tooltip sortable="custom"/>
|
||||||
|
<el-table-column label="访视名称" prop="VisitName" min-width="90" show-overflow-tooltip sortable="custom"/>
|
||||||
|
<el-table-column label="检查编号" prop="StudyCode" min-width="90" show-overflow-tooltip sortable="custom"/>
|
||||||
|
<el-table-column label="文件数" prop="FileCount" min-width="90" show-overflow-tooltip/>
|
||||||
|
<el-table-column label="源区域" prop="UploadRegion" min-width="60" show-overflow-tooltip />
|
||||||
|
<el-table-column label="源可用时间" prop="CreateTime" min-width="90" show-overflow-tooltip />
|
||||||
|
<el-table-column label="目标区域" prop="TargetRegion" min-width="60" show-overflow-tooltip />
|
||||||
|
<el-table-column label="目标可用时间" prop="SyncFinishedTime" min-width="90" show-overflow-tooltip/>
|
||||||
|
<el-table-column label="是否同步完成" prop="IsSync" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.IsSync" type="success">
|
||||||
|
{{ $fd('YesOrNo', scope.row.IsSync) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else type="danger">
|
||||||
|
{{ $fd('YesOrNo', scope.row.IsSync) }}
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="操作" min-width="80" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="primary" size="small" @click="openDetailTable(scope.row)">
|
||||||
|
详情
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</template>
|
||||||
|
<el-dialog
|
||||||
|
v-if="detailDialog.visible"
|
||||||
|
:visible.sync="detailDialog.visible"
|
||||||
|
fullscreen
|
||||||
|
append-to-body
|
||||||
|
:close-on-click-modal="false"
|
||||||
|
class="detail-dialog"
|
||||||
|
>
|
||||||
|
<span slot="title">{{ detailDialog.title }}</span>
|
||||||
|
<span v-if="detailDialog.currentRow">{{`${detailDialog.currentRow.SubjectCode} / ${detailDialog.currentRow.VisitName} ${detailDialog.currentRow.StudyCode ? ' / ' + detailDialog.currentRow.StudyCode : ''} (源:${detailDialog.currentRow.UploadRegion} -> 目标:${detailDialog.currentRow.TargetRegion})`}}</span>
|
||||||
|
<el-tabs class="detail-tabs" v-model="detailDialog.activeTab" @tab-click="handleDetailTabClick">
|
||||||
|
<el-tab-pane label="文件级别" name="file">
|
||||||
|
<FileList
|
||||||
|
v-if="detailDialog.activeTab === 'file'"
|
||||||
|
:dataFileType="1"
|
||||||
|
:rowInfo="detailDialog.currentRow"
|
||||||
|
@openTaskTable="openTaskTable"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="任务级别" name="task">
|
||||||
|
<TaskList
|
||||||
|
v-if="detailDialog.activeTab === 'task'"
|
||||||
|
:rowInfo="detailDialog.currentRow"
|
||||||
|
:fileUploadRecordId="fileUploadRecordId"
|
||||||
|
:path="path"
|
||||||
|
/>
|
||||||
|
</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</el-dialog>
|
||||||
|
</BaseContainer>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { getSubjectUploadRecordList } from '@/api/file'
|
||||||
|
import { getTrialVisitStageSelect } from '@/api/trials'
|
||||||
|
import BaseContainer from '@/components/BaseContainer'
|
||||||
|
import Pagination from '@/components/Pagination'
|
||||||
|
import FileList from './FileList'
|
||||||
|
import TaskList from './TaskList'
|
||||||
|
import moment from 'moment'
|
||||||
|
const searchDataDefault = () => {
|
||||||
|
return {
|
||||||
|
TrialId: '',
|
||||||
|
SubjectCode: '',
|
||||||
|
VisitName: null,
|
||||||
|
StudyCode: '',
|
||||||
|
UploadRegion: '',
|
||||||
|
TargetRegion: '',
|
||||||
|
IsSync: null,
|
||||||
|
// UploadStartTime: null,
|
||||||
|
// UploadEndTime: null,
|
||||||
|
// SyncFinishedStartTime: null,
|
||||||
|
// SyncFinishedEndTime: null,
|
||||||
|
PageIndex: 1,
|
||||||
|
PageSize: 20,
|
||||||
|
Asc: true,
|
||||||
|
SortField: 'StudyCode'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
components: { BaseContainer, Pagination, FileList, TaskList },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
trialId: '',
|
||||||
|
moment,
|
||||||
|
searchData: searchDataDefault(),
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
loading: false,
|
||||||
|
visitPlanOptions: [],
|
||||||
|
detailDialog: {
|
||||||
|
visible: false,
|
||||||
|
title: '详情',
|
||||||
|
activeTab: 'file',
|
||||||
|
currentRow: null
|
||||||
|
},
|
||||||
|
regionOptions: [
|
||||||
|
{
|
||||||
|
value: 'CN',
|
||||||
|
label: 'CN'
|
||||||
|
}, {
|
||||||
|
value: 'US',
|
||||||
|
label: 'US'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
fileUploadRecordId: '',
|
||||||
|
path: '',
|
||||||
|
uploadTimeRange: null,
|
||||||
|
SyncTimeRange: null,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.trialId = this.$route.query.trialId
|
||||||
|
this.getList()
|
||||||
|
this.getVisitPlanOptions()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getList() {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
this.searchData.TrialId = this.trialId
|
||||||
|
let res = await getSubjectUploadRecordList(this.searchData)
|
||||||
|
this.loading = false
|
||||||
|
this.list = res.Result.CurrentPageData
|
||||||
|
this.total = res.Result.TotalCount
|
||||||
|
} catch(e) {
|
||||||
|
this.loading = false
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
openDetailTable(row) {
|
||||||
|
this.detailDialog.currentRow = row || null
|
||||||
|
this.detailDialog.activeTab = 'file'
|
||||||
|
this.detailDialog.visible = true
|
||||||
|
},
|
||||||
|
openTaskTable(row) {
|
||||||
|
this.fileUploadRecordId = row.Id
|
||||||
|
this.path = row.Path
|
||||||
|
this.detailDialog.activeTab = 'task'
|
||||||
|
|
||||||
|
},
|
||||||
|
handleDetailTabClick(tab) {
|
||||||
|
const name = tab.name
|
||||||
|
if (name === 'file') {
|
||||||
|
this.fileUploadRecordId = ''
|
||||||
|
this.path = ''
|
||||||
|
}
|
||||||
|
// if (name !== 'upload' && name !== 'sync') return
|
||||||
|
// if (this.detailDialog[name].list && this.detailDialog[name].list.length) return
|
||||||
|
// this.fetchDetailList(name)
|
||||||
|
},
|
||||||
|
// 获取访视下拉框数据
|
||||||
|
async getVisitPlanOptions() {
|
||||||
|
try {
|
||||||
|
let res = await getTrialVisitStageSelect(this.trialId)
|
||||||
|
this.visitPlanOptions = res.Result
|
||||||
|
} catch(e) {
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleUploadtimeChange(val) {
|
||||||
|
if (val) {
|
||||||
|
this.searchData.UploadStartTime = val[0]
|
||||||
|
this.searchData.UploadEndTime = val[1]
|
||||||
|
} else {
|
||||||
|
this.searchData.UploadStartTime = ''
|
||||||
|
this.searchData.UploadEndTime = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSynctimeChange(val) {
|
||||||
|
if (val) {
|
||||||
|
this.searchData.SyncFinishedStartTime = val[0]
|
||||||
|
this.searchData.SyncFinishedEndTime = val[1]
|
||||||
|
} else {
|
||||||
|
this.searchData.SyncFinishedStartTime = ''
|
||||||
|
this.searchData.SyncFinishedEndTime = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSearch() {
|
||||||
|
this.searchData.PageIndex = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 重置列表查询
|
||||||
|
handleReset() {
|
||||||
|
// this.uploadTimeRange = null
|
||||||
|
// this.handleUploadtimeChange()
|
||||||
|
// this.SyncTimeRange = null
|
||||||
|
// this.handleSynctimeChange()
|
||||||
|
this.searchData = searchDataDefault()
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.detail-dialog {
|
||||||
|
margin: 0;
|
||||||
|
height: 100vh;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
.el-dialog__header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-dialog__body {
|
||||||
|
padding-top: 10px;
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.is-fullscreen {
|
||||||
|
.el-dialog__body {
|
||||||
|
margin-top: 10px;
|
||||||
|
height: calc(100% - 80px);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.detail-tabs {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.el-tabs__header {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
margin: 0 0 8px;
|
||||||
|
}
|
||||||
|
.el-tabs__content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.el-tab-pane {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
@ -0,0 +1,249 @@
|
||||||
|
<template>
|
||||||
|
<BaseContainer>
|
||||||
|
<template slot="search-container">
|
||||||
|
<el-form :inline="true">
|
||||||
|
<!-- 文件名称 -->
|
||||||
|
<el-form-item label="文件名称" prop="FileName">
|
||||||
|
<el-input v-model="searchData.FileName" size="small" clearable style="width: 120px" />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 文件路径 -->
|
||||||
|
<el-form-item label="文件路径" prop="Path">
|
||||||
|
<el-input v-model="searchData.Path" size="small" clearable />
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 任务状态 -->
|
||||||
|
<el-form-item label="任务状态" prop="JobState">
|
||||||
|
<el-select v-model="searchData.JobState" clearable style="width: 120px">
|
||||||
|
<el-option
|
||||||
|
v-for="item of $d.JobState"
|
||||||
|
:key="'JobState' + item.label"
|
||||||
|
:value="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 任务开始日期 -->
|
||||||
|
<el-form-item label="任务开始日期">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchData.StartTime"
|
||||||
|
type="date"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
:picker-options="beginPickerOption"
|
||||||
|
style="width:140px;"
|
||||||
|
/>
|
||||||
|
</el-form-item>
|
||||||
|
<!-- 任务结束日期 -->
|
||||||
|
<el-form-item label="任务结束日期">
|
||||||
|
<el-date-picker
|
||||||
|
v-model="searchData.EndTime"
|
||||||
|
type="date"
|
||||||
|
value-format="yyyy-MM-dd"
|
||||||
|
format="yyyy-MM-dd"
|
||||||
|
:picker-options="endpickerOption"
|
||||||
|
style="width:140px;"
|
||||||
|
/>
|
||||||
|
</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-form>
|
||||||
|
</template>
|
||||||
|
<template slot="main-container">
|
||||||
|
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 70 }" height="100" :data="list"
|
||||||
|
class="table" @sort-change="handleSortByColumn" :default-sort="{ prop: 'CreateTime', order: 'descending' }">
|
||||||
|
<el-table-column type="index" width="50" />
|
||||||
|
<el-table-column label="Job编号" prop="Id" min-width="90" show-overflow-tooltip/>
|
||||||
|
<el-table-column label="文件名称" prop="FileName" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="路径" prop="Path" min-width="90" show-overflow-tooltip/>
|
||||||
|
<el-table-column label="任务状态" prop="JobState" min-width="90" show-overflow-tooltip sortable="custom">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-tag v-if="scope.row.JobState === 1" type="infoinf0">
|
||||||
|
{{ $fd('JobState', scope.row.JobState) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.JobState === 1" type="warning">
|
||||||
|
{{ $fd('JobState', scope.row.JobState) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.JobState === 2" type="success">
|
||||||
|
{{ $fd('JobState', scope.row.JobState) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else-if="scope.row.JobState === 3" type="danger">
|
||||||
|
{{ $fd('JobState', scope.row.JobState) }}
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-else>{{ $fd('JobState', scope.row.JobState) }}</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column label="任务开始时间" prop="StartTime" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="任务结束时间" prop="EndTime" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
<el-table-column label="创建时间" prop="CreateTime" min-width="90" show-overflow-tooltip sortable="custom" />
|
||||||
|
|
||||||
|
|
||||||
|
<el-table-column label="操作" min-width="80" show-overflow-tooltip>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<el-button type="primary" size="mini" :disabled="scope.row.JobState !== 3" @click="execute(scope.row)">
|
||||||
|
再次执行
|
||||||
|
</el-button>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
</template>
|
||||||
|
</BaseContainer>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { getUploadFileSyncRecordList, batchAddSyncFileTask } from '@/api/file'
|
||||||
|
import BaseContainer from '@/components/BaseContainer'
|
||||||
|
import Pagination from '@/components/Pagination'
|
||||||
|
import moment from 'moment'
|
||||||
|
const searchDataDefault = () => {
|
||||||
|
return {
|
||||||
|
TrialId: '',
|
||||||
|
StudyCode: '',
|
||||||
|
SubjectCode: '',
|
||||||
|
VisitName: '',
|
||||||
|
FileUploadRecordId: '',
|
||||||
|
JobState: null,
|
||||||
|
FileName: '',
|
||||||
|
Path: '',
|
||||||
|
StartTime: '',
|
||||||
|
EndTime: '',
|
||||||
|
Asc: false,
|
||||||
|
SortField: '',
|
||||||
|
PageIndex: 1,
|
||||||
|
PageSize: 20,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default {
|
||||||
|
name: 'TaskList',
|
||||||
|
components: { BaseContainer, Pagination },
|
||||||
|
props: {
|
||||||
|
fileUploadRecordId: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
rowInfo: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
moment,
|
||||||
|
searchData: searchDataDefault(),
|
||||||
|
list: [],
|
||||||
|
total: 0,
|
||||||
|
loading: false,
|
||||||
|
datetimerange: [],
|
||||||
|
beginPickerOption: {
|
||||||
|
disabledDate: time => {
|
||||||
|
if (this.searchData.EndTime) {
|
||||||
|
return time.getTime() >= new Date(this.searchData.EndTime).getTime()
|
||||||
|
} else {
|
||||||
|
return time.getTime() > Date.now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
endpickerOption: {
|
||||||
|
disabledDate: time => {
|
||||||
|
if (this.searchData.StartTime) {
|
||||||
|
return time.getTime() > Date.now() || time.getTime() <= new Date(this.searchData.StartTime).getTime() - 86400000
|
||||||
|
} else {
|
||||||
|
return time.getTime() > Date.now()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(()=>{
|
||||||
|
this.searchData.Path = this.path
|
||||||
|
this.searchData.FileUploadRecordId = this.fileUploadRecordId
|
||||||
|
this.getList()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getList() {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
this.searchData.TrialId = this.$route.query.trialId
|
||||||
|
this.searchData.StudyCode = this.rowInfo.StudyCode
|
||||||
|
this.searchData.SubjectCode = this.rowInfo.SubjectCode
|
||||||
|
this.searchData.VisitName = this.rowInfo.VisitName
|
||||||
|
|
||||||
|
let res = await getUploadFileSyncRecordList(this.searchData)
|
||||||
|
this.loading = false
|
||||||
|
this.list = res.Result.CurrentPageData
|
||||||
|
this.total = res.Result.TotalCount
|
||||||
|
} catch(e) {
|
||||||
|
this.loading = false
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
async execute(row) {
|
||||||
|
try {
|
||||||
|
this.loading = true
|
||||||
|
let params = {
|
||||||
|
fileUploadRecordIdList: [row.Id]
|
||||||
|
}
|
||||||
|
let res = await batchAddSyncFileTask(params)
|
||||||
|
if (res.IsSuccess) {
|
||||||
|
this.$message.success('执行成功!')
|
||||||
|
}
|
||||||
|
|
||||||
|
this.loading = false
|
||||||
|
this.getList()
|
||||||
|
} catch(e) {
|
||||||
|
this.loading = false
|
||||||
|
console.log(e)
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
fileSizeFormatter(size) {
|
||||||
|
if (!size) return
|
||||||
|
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
|
||||||
|
},
|
||||||
|
handleDatetimeChange(val) {
|
||||||
|
if (val) {
|
||||||
|
this.searchData.BeginDate = val[0]
|
||||||
|
this.searchData.EndDate = val[1]
|
||||||
|
} else {
|
||||||
|
this.searchData.BeginDate = ''
|
||||||
|
this.searchData.EndDate = ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleSearch() {
|
||||||
|
this.searchData.PageIndex = 1
|
||||||
|
this.getList()
|
||||||
|
},
|
||||||
|
// 重置列表查询
|
||||||
|
handleReset() {
|
||||||
|
this.datetimerange = null
|
||||||
|
this.searchData = searchDataDefault()
|
||||||
|
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()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
<template>
|
||||||
|
<el-tabs class="data-sync-tabs" type="border-card" tab-position="left" v-model="activeTab" >
|
||||||
|
<el-tab-pane label="检查列表" name="study">
|
||||||
|
<StudyList />
|
||||||
|
</el-tab-pane>
|
||||||
|
<el-tab-pane label="其他" name="other">其他</el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import StudyList from './components/StudyList'
|
||||||
|
export default {
|
||||||
|
name: 'DataSync',
|
||||||
|
components: {
|
||||||
|
StudyList
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
activeTab: 'study'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style lang="scss">
|
||||||
|
.data-sync-tabs{
|
||||||
|
height: 100%;
|
||||||
|
background-color: #fff;
|
||||||
|
.el-tabs__header {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.el-tabs__content {
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
.el-tab-pane {
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
@ -36,17 +36,49 @@
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import BaseContainer from '@/components/BaseContainer'
|
import BaseContainer from '@/components/BaseContainer'
|
||||||
let echarts = require('echarts/lib/echarts');
|
import * as echarts from 'echarts/core';
|
||||||
|
import { BarChart, FunnelChart } from 'echarts/charts';
|
||||||
|
import {
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
LegendComponent,
|
||||||
|
MarkLineComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
// 内置数据转换器组件 (filter, sort)
|
||||||
|
TransformComponent
|
||||||
|
} from 'echarts/components';
|
||||||
|
// 标签自动布局、全局过渡动画等特性
|
||||||
|
import { LabelLayout, UniversalTransition } from 'echarts/features';
|
||||||
|
// 引入 Canvas 渲染器,注意引入 CanvasRenderer 或者 SVGRenderer 是必须的一步
|
||||||
|
import { CanvasRenderer } from 'echarts/renderers';
|
||||||
|
echarts.use([
|
||||||
|
TitleComponent,
|
||||||
|
TooltipComponent,
|
||||||
|
GridComponent,
|
||||||
|
DatasetComponent,
|
||||||
|
TransformComponent,
|
||||||
|
DataZoomComponent,
|
||||||
|
MarkLineComponent,
|
||||||
|
LegendComponent,
|
||||||
|
BarChart,
|
||||||
|
FunnelChart,
|
||||||
|
LabelLayout,
|
||||||
|
UniversalTransition,
|
||||||
|
CanvasRenderer
|
||||||
|
]);
|
||||||
|
// let echarts = require('echarts/lib/echarts');
|
||||||
|
|
||||||
require('echarts/lib/component/markLine');
|
// require('echarts/lib/component/markLine');
|
||||||
require('echarts/lib/chart/funnel');
|
// require('echarts/lib/chart/funnel');
|
||||||
require('echarts/lib/chart/bar');
|
// require('echarts/lib/chart/bar');
|
||||||
// 按需引入组件
|
// 按需引入组件
|
||||||
require('echarts/lib/component/tooltip');
|
// require('echarts/lib/component/tooltip');
|
||||||
require('echarts/lib/component/title');
|
// require('echarts/lib/component/title');
|
||||||
require('echarts/lib/component/legend');
|
// require('echarts/lib/component/legend');
|
||||||
require('echarts/lib/component/grid');
|
// require('echarts/lib/component/grid');
|
||||||
require('echarts/lib/component/dataZoom');
|
// require('echarts/lib/component/dataZoom');
|
||||||
import {
|
import {
|
||||||
getTrialCriterionList,
|
getTrialCriterionList,
|
||||||
getTrialVisitFinishedStatList,
|
getTrialVisitFinishedStatList,
|
||||||
|
|
@ -178,8 +210,11 @@ export default {
|
||||||
this.chart_left = echarts.init(this.$refs.chartContainer_left);
|
this.chart_left = echarts.init(this.$refs.chartContainer_left);
|
||||||
// ...图表配置
|
// ...图表配置
|
||||||
const option = {
|
const option = {
|
||||||
|
richInheritPlainLabel: false,
|
||||||
title: {
|
title: {
|
||||||
text: obj.titleText
|
text: obj.titleText,
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
},
|
},
|
||||||
color: this.color,
|
color: this.color,
|
||||||
tooltip: {
|
tooltip: {
|
||||||
|
|
@ -316,7 +351,13 @@ export default {
|
||||||
// ...图表配置
|
// ...图表配置
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
text: obj.titleText
|
text: obj.titleText,
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 80,
|
||||||
|
bottom: 50
|
||||||
},
|
},
|
||||||
toolbox: {
|
toolbox: {
|
||||||
show: false
|
show: false
|
||||||
|
|
@ -339,6 +380,9 @@ export default {
|
||||||
],
|
],
|
||||||
yAxis: [
|
yAxis: [
|
||||||
{
|
{
|
||||||
|
axisLine: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
name: obj.unit,
|
name: obj.unit,
|
||||||
type: 'value'
|
type: 'value'
|
||||||
}
|
}
|
||||||
|
|
@ -424,12 +468,18 @@ export default {
|
||||||
// ...图表配置
|
// ...图表配置
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
text: obj.titleText
|
text: obj.titleText,
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
},
|
},
|
||||||
toolbox: {
|
toolbox: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
color: this.color,
|
color: this.color,
|
||||||
|
grid: {
|
||||||
|
left: 80,
|
||||||
|
bottom: 50
|
||||||
|
},
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'axis',
|
trigger: 'axis',
|
||||||
axisPointer: {
|
axisPointer: {
|
||||||
|
|
@ -441,6 +491,9 @@ export default {
|
||||||
data: obj.xAxisData
|
data: obj.xAxisData
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
|
axisLine: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
name: obj.unit,
|
name: obj.unit,
|
||||||
type: 'value',
|
type: 'value',
|
||||||
minInterval: 1
|
minInterval: 1
|
||||||
|
|
@ -474,11 +527,17 @@ export default {
|
||||||
// ...图表配置
|
// ...图表配置
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
text: obj.titleText
|
text: obj.titleText,
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
},
|
},
|
||||||
toolbox: {
|
toolbox: {
|
||||||
show: false
|
show: false
|
||||||
},
|
},
|
||||||
|
grid: {
|
||||||
|
left: 80,
|
||||||
|
bottom: 50
|
||||||
|
},
|
||||||
color: this.color,
|
color: this.color,
|
||||||
tooltip: {
|
tooltip: {
|
||||||
trigger: 'item',
|
trigger: 'item',
|
||||||
|
|
@ -498,8 +557,11 @@ export default {
|
||||||
yAxis: {
|
yAxis: {
|
||||||
name: obj.unit,
|
name: obj.unit,
|
||||||
type: 'value',
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
show: true
|
||||||
|
},
|
||||||
axisLabel: {
|
axisLabel: {
|
||||||
formatter: '{value}%'
|
formatter: '{value}%',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
series: {
|
series: {
|
||||||
|
|
@ -531,7 +593,13 @@ export default {
|
||||||
// ...图表配置
|
// ...图表配置
|
||||||
const option = {
|
const option = {
|
||||||
title: {
|
title: {
|
||||||
text: obj.titleText
|
text: obj.titleText,
|
||||||
|
left: 0,
|
||||||
|
top: 0
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 80,
|
||||||
|
bottom: 50
|
||||||
},
|
},
|
||||||
toolbox: {
|
toolbox: {
|
||||||
show: false
|
show: false
|
||||||
|
|
@ -550,7 +618,10 @@ export default {
|
||||||
},
|
},
|
||||||
yAxis: {
|
yAxis: {
|
||||||
name: obj.unit,
|
name: obj.unit,
|
||||||
type: 'value'
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
show: true
|
||||||
|
}
|
||||||
},
|
},
|
||||||
series: {
|
series: {
|
||||||
markLine: {
|
markLine: {
|
||||||
|
|
|
||||||
|
|
@ -382,6 +382,7 @@ export default {
|
||||||
size: files[i].size,
|
size: files[i].size,
|
||||||
type: extendName.split('.')[1],
|
type: extendName.split('.')[1],
|
||||||
file: files[i],
|
file: files[i],
|
||||||
|
fileType: files[i].type
|
||||||
}
|
}
|
||||||
this.fileList.push(obj);
|
this.fileList.push(obj);
|
||||||
}
|
}
|
||||||
|
|
@ -401,7 +402,17 @@ export default {
|
||||||
var timestamp = Date.now();
|
var timestamp = Date.now();
|
||||||
const res = await this.OSSclient.put(
|
const res = await this.OSSclient.put(
|
||||||
`/${this.trialId}/ClinicalData/${timestamp}_${this.fileList[i].file.name}`,
|
`/${this.trialId}/ClinicalData/${timestamp}_${this.fileList[i].file.name}`,
|
||||||
file
|
file,
|
||||||
|
{
|
||||||
|
fileName: `${this.fileList[i].file.name}`,
|
||||||
|
fileSize: file.size,
|
||||||
|
fileType: this.fileList[i].fileType,
|
||||||
|
uploadBatchId: this.$guid(),
|
||||||
|
batchDataType: 4,
|
||||||
|
trialId: this.trialId,
|
||||||
|
subjectId: this.data.SubjectId,
|
||||||
|
subjectVisitId: this.subjectVisitId
|
||||||
|
}
|
||||||
);
|
);
|
||||||
this.addFileList.push({
|
this.addFileList.push({
|
||||||
fileName: this.fileList[i].file.name,
|
fileName: this.fileList[i].file.name,
|
||||||
|
|
|
||||||
|
|
@ -1520,6 +1520,7 @@ export default {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
let arr = []
|
let arr = []
|
||||||
|
let uploadBatchId = scope.$guid()
|
||||||
for (let i = 0; i < seriesList.length; i++) {
|
for (let i = 0; i < seriesList.length; i++) {
|
||||||
let v = seriesList[i]
|
let v = seriesList[i]
|
||||||
let instanceList = []
|
let instanceList = []
|
||||||
|
|
@ -1587,6 +1588,7 @@ export default {
|
||||||
params.trialId
|
params.trialId
|
||||||
)}`
|
)}`
|
||||||
if (scope.isClose) return
|
if (scope.isClose) return
|
||||||
|
console.log(o.file)
|
||||||
let res = await dcmUpload(
|
let res = await dcmUpload(
|
||||||
{
|
{
|
||||||
path: path,
|
path: path,
|
||||||
|
|
@ -1607,6 +1609,16 @@ export default {
|
||||||
) {
|
) {
|
||||||
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
dicomInfo.uploadFileSize = dicomInfo.fileSize
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileName: o.file.name,
|
||||||
|
fileSize: o.file.size,
|
||||||
|
fileType: 'application/dicom',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 1,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (!res || !res.url) {
|
if (!res || !res.url) {
|
||||||
|
|
@ -1623,11 +1635,22 @@ export default {
|
||||||
o.imageColumns,
|
o.imageColumns,
|
||||||
o.imageRows
|
o.imageRows
|
||||||
)
|
)
|
||||||
|
|
||||||
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
let thumbnailPath = `/${params.trialId}/Image/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||||
let OSSclient = scope.OSSclient
|
let OSSclient = scope.OSSclient
|
||||||
let seriesRes = await OSSclient.put(
|
let seriesRes = await OSSclient.put(
|
||||||
thumbnailPath,
|
thumbnailPath,
|
||||||
blob
|
blob,
|
||||||
|
{
|
||||||
|
fileName: `${v.seriesUid}.jpg`,
|
||||||
|
fileSize: blob.size,
|
||||||
|
fileType: 'image/jpeg',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 2,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId
|
||||||
|
}
|
||||||
)
|
)
|
||||||
if (seriesRes && seriesRes.url) {
|
if (seriesRes && seriesRes.url) {
|
||||||
ImageResizePath = scope.$getObjectName(
|
ImageResizePath = scope.$getObjectName(
|
||||||
|
|
@ -1762,7 +1785,20 @@ export default {
|
||||||
let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
let thumbnailPath = `/${params.trialId}/Image/${params.trialSiteId}/${params.subjectId}/${params.subjectVisitId}/${dicomInfo.studyUid}/${v.seriesUid}.jpg`
|
||||||
let OSSclient = scope.OSSclient
|
let OSSclient = scope.OSSclient
|
||||||
try {
|
try {
|
||||||
let seriesRes = await OSSclient.put(thumbnailPath, blob)
|
let seriesRes = await OSSclient.put(
|
||||||
|
thumbnailPath,
|
||||||
|
blob,
|
||||||
|
{
|
||||||
|
fileName: `${v.seriesUid}.jpg`,
|
||||||
|
fileSize: blob.size,
|
||||||
|
fileType: 'image/jpeg',
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 2,
|
||||||
|
trialId: params.trialId,
|
||||||
|
subjectId: params.subjectId,
|
||||||
|
subjectVisitId: params.subjectVisitId
|
||||||
|
}
|
||||||
|
)
|
||||||
if (seriesRes && seriesRes.url) {
|
if (seriesRes && seriesRes.url) {
|
||||||
o.ImageResizePath = scope.$getObjectName(seriesRes.url)
|
o.ImageResizePath = scope.$getObjectName(seriesRes.url)
|
||||||
}
|
}
|
||||||
|
|
@ -1775,7 +1811,8 @@ export default {
|
||||||
params.study.instanceCount = dicomInfo.failedFileCount
|
params.study.instanceCount = dicomInfo.failedFileCount
|
||||||
params.RecordPath = scope.$getObjectName(logRes.url)
|
params.RecordPath = scope.$getObjectName(logRes.url)
|
||||||
if (scope.isClose) return false
|
if (scope.isClose) return false
|
||||||
console.log(params)
|
|
||||||
|
params.UploadBatchId = uploadBatchId
|
||||||
addOrUpdateArchiveStudy(params)
|
addOrUpdateArchiveStudy(params)
|
||||||
.then((res) => {
|
.then((res) => {
|
||||||
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
if (dicomInfo.failedFileCount === dicomInfo.fileCount) {
|
||||||
|
|
|
||||||
|
|
@ -756,6 +756,7 @@ export default {
|
||||||
.substring(fileName.lastIndexOf('.'))
|
.substring(fileName.lastIndexOf('.'))
|
||||||
.toLocaleLowerCase()
|
.toLocaleLowerCase()
|
||||||
if (this.faccept.indexOf(extendName) !== -1) {
|
if (this.faccept.indexOf(extendName) !== -1) {
|
||||||
|
files[i].fileName = files[i].name
|
||||||
files[i].id = `${files[i].lastModified}${files[i].name}`
|
files[i].id = `${files[i].lastModified}${files[i].name}`
|
||||||
this.fileList.push(files[i])
|
this.fileList.push(files[i])
|
||||||
}
|
}
|
||||||
|
|
@ -809,8 +810,9 @@ export default {
|
||||||
})
|
})
|
||||||
if (res.IsSuccess) {
|
if (res.IsSuccess) {
|
||||||
this.studyMonitorId = res.Result
|
this.studyMonitorId = res.Result
|
||||||
|
let uploadBatchId = this.$guid()
|
||||||
for (let i = 0; i < num; i++) {
|
for (let i = 0; i < num; i++) {
|
||||||
funArr.push(this.handleUploadTask(this.selectArr, i))
|
funArr.push(this.handleUploadTask(this.selectArr, i, uploadBatchId))
|
||||||
}
|
}
|
||||||
if (funArr.length > 0) {
|
if (funArr.length > 0) {
|
||||||
let res = await Promise.all(funArr)
|
let res = await Promise.all(funArr)
|
||||||
|
|
@ -821,17 +823,16 @@ export default {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// 并发上传
|
// 并发上传
|
||||||
async handleUploadTask(arr, index) {
|
async handleUploadTask(arr, index, uploadBatchId) {
|
||||||
if (!this.uploadVisible) return
|
if (!this.uploadVisible) return
|
||||||
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
||||||
file.status = 1
|
file.status = 1
|
||||||
|
let fileName = `${this.$guid()}${file.name.substring(file.name.lastIndexOf('.')).toLocaleLowerCase()}`
|
||||||
let path = `/${this.trialId}/Image/${this.data.SubjectId}/${this.data.Id
|
let path = `/${this.trialId}/Image/${this.data.SubjectId}/${this.data.Id
|
||||||
}/${this.$guid()}${file.name
|
}/${fileName}`
|
||||||
.substring(file.name.lastIndexOf('.'))
|
|
||||||
.toLocaleLowerCase()}`
|
|
||||||
file.curPath = path
|
file.curPath = path
|
||||||
const fileData = await this.fileToBlob(file.file)
|
const fileData = await this.fileToBlob(file.file)
|
||||||
let res = await this.fileToOss(path, fileData, file)
|
let res = await this.fileToOss(path, fileData, file, uploadBatchId)
|
||||||
if (res) {
|
if (res) {
|
||||||
file.status = 2
|
file.status = 2
|
||||||
this.successFileList.push({
|
this.successFileList.push({
|
||||||
|
|
@ -865,13 +866,13 @@ export default {
|
||||||
}
|
}
|
||||||
let ind = arr.findIndex((item) => item.status === 0)
|
let ind = arr.findIndex((item) => item.status === 0)
|
||||||
if (ind >= 0) {
|
if (ind >= 0) {
|
||||||
return this.handleUploadTask(arr, ind)
|
return this.handleUploadTask(arr, ind, uploadBatchId)
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// file上传到oss
|
// file上传到oss
|
||||||
async fileToOss(path, file, item) {
|
async fileToOss(path, file, item, uploadBatchId) {
|
||||||
try {
|
try {
|
||||||
let res = await this.OSSclient.multipartUpload(
|
let res = await this.OSSclient.multipartUpload(
|
||||||
{
|
{
|
||||||
|
|
@ -884,6 +885,18 @@ export default {
|
||||||
if (item.uploadFileSize > file.fileSize) {
|
if (item.uploadFileSize > file.fileSize) {
|
||||||
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
item.uploadFileSize = file.fileSize > 0 ? file.fileSize : 1
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileName: item.name,
|
||||||
|
fileSize: item.size,
|
||||||
|
fileType: item.fileType,
|
||||||
|
uploadBatchId: uploadBatchId,
|
||||||
|
batchDataType: 3,
|
||||||
|
trialId: this.trialId,
|
||||||
|
subjectId: this.data.SubjectId,
|
||||||
|
subjectVisitId: this.subjectVisitId,
|
||||||
|
studyCode: this.currentRow.CodeView
|
||||||
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
if (res) {
|
if (res) {
|
||||||
|
|
|
||||||
|
|
@ -361,6 +361,7 @@ export default {
|
||||||
size: files[i].size,
|
size: files[i].size,
|
||||||
type: extendName.split('.')[1],
|
type: extendName.split('.')[1],
|
||||||
file: files[i],
|
file: files[i],
|
||||||
|
fileType: files[i].type
|
||||||
}
|
}
|
||||||
this.fileList.push(obj)
|
this.fileList.push(obj)
|
||||||
}
|
}
|
||||||
|
|
@ -380,7 +381,17 @@ export default {
|
||||||
var timestamp = Date.now()
|
var timestamp = Date.now()
|
||||||
const res = await this.OSSclient.put(
|
const res = await this.OSSclient.put(
|
||||||
`/${this.trialId}/ClinicalData/${timestamp}_${this.fileList[i].file.name}`,
|
`/${this.trialId}/ClinicalData/${timestamp}_${this.fileList[i].file.name}`,
|
||||||
file
|
file,
|
||||||
|
{
|
||||||
|
fileName: `${this.fileList[i].file.name}`,
|
||||||
|
fileSize: this.fileList[i].size,
|
||||||
|
fileType: this.fileList[i].fileType,
|
||||||
|
uploadBatchId: this.$guid(),
|
||||||
|
batchDataType: 4,
|
||||||
|
trialId: this.trialId,
|
||||||
|
subjectId: this.data.SubjectId,
|
||||||
|
subjectVisitId: this.subjectVisitId
|
||||||
|
}
|
||||||
)
|
)
|
||||||
this.addFileList.push({
|
this.addFileList.push({
|
||||||
fileName: this.fileList[i].file.name,
|
fileName: this.fileList[i].file.name,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue