14 Commits

Author SHA1 Message Date
wangxiaoshuang e0321bae72 影像预览问题解决
continuous-integration/drone/push Build encountered an error
2025-04-12 12:04:20 +08:00
wangxiaoshuang 1e720e399d 确认收入项,修改选项后,其他文件也改了
continuous-integration/drone/push Build encountered an error
2025-04-03 11:15:54 +08:00
wangxiaoshuang 1368397da9 项目总览—>上传记录:中心编号 查询条件,查询结果不对 2025-04-03 11:15:36 +08:00
wangxiaoshuang c8c049b5d0 DICOM影像中,存在Tag最大像素值、最小像素值等,但是和实际的数据统计结果不同 2025-04-03 11:15:22 +08:00
wangxiaoshuang 7fcbd7f983 生产环境配置修改
continuous-integration/drone/push Build encountered an error
2025-03-24 13:59:21 +08:00
wangxiaoshuang 779badb041 项目文档系统数据中英文转换
continuous-integration/drone/push Build is passing
2025-03-24 09:31:49 +08:00
caiyiling ef5e5527fd 标注更改及检查名称更改
continuous-integration/drone/push Build is passing
2025-03-21 16:29:47 +08:00
caiyiling 52ac12d6b6 阅片页面显示检查名称
continuous-integration/drone/push Build is passing
2025-03-21 15:36:23 +08:00
caiyiling 272c28a988 自定义阅片更改及非dicom阅片添加个性化配置
continuous-integration/drone/push Build is passing
2025-03-21 15:03:21 +08:00
caiyiling 6b10d07e2a 自定义阅片预览paf更改
continuous-integration/drone/push Build is passing
2025-03-21 14:03:53 +08:00
caiyiling 032e710890 阅片工具及报告页查看pdf更改
continuous-integration/drone/push Build is passing
2025-03-21 13:09:36 +08:00
caiyiling 032150904e 非dicom阅片更改
continuous-integration/drone/push Build is passing
2025-03-20 19:23:20 +08:00
wangxiaoshuang d91161a139 网速监控改为三位小数
continuous-integration/drone/push Build is passing
2025-03-19 15:53:41 +08:00
wangxiaoshuang bba2237337 文件大小改为保留3位小数
continuous-integration/drone/push Build is passing
2025-03-19 15:36:53 +08:00
40 changed files with 1370 additions and 445 deletions
+3
View File
@@ -2,6 +2,9 @@
ENV = 'prop'
NODE_ENV = 'prop'
# base public path
VUE_APP_BASE_PATH = '/'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true
+197
View File
File diff suppressed because one or more lines are too long
@@ -316,9 +316,9 @@
scope.row.dicomInfo.fileCount
}}
({{
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(2)
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(3)
}}MB/{{
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(2)
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(3)
}}MB)
</span>
</template>
@@ -66,7 +66,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -138,7 +138,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -320,7 +320,7 @@
<template slot-scope="scope">
<span>{{
scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
+1
View File
@@ -862,6 +862,7 @@ const actions = {
const data = {}
data.StudyId = study.StudyId
data.StudyCode = study.StudyCode
data.StudyName = study.StudyName
data.Modalities = study.Modalities
data.SeriesCount = study.SeriesCount
data.InstanceCount = study.InstanceCount
+149
View File
@@ -39,6 +39,108 @@ function getNumberValues(dataSet, tag, minimumLength) {
return values;
}
function getLutDescriptor(dataSet, tag) {
if (!dataSet.elements[tag] || dataSet.elements[tag].length !== 6) {
return;
}
return [
dataSet.uint16(tag, 0),
dataSet.uint16(tag, 1),
dataSet.uint16(tag, 2),
];
}
function getLutData(lutDataSet, tag, lutDescriptor) {
const lut = [];
const lutData = lutDataSet.elements[tag];
for (let i = 0; i < lutDescriptor[0]; i++) {
// Output range is always unsigned
if (lutDescriptor[2] === 16) {
lut[i] = lutDataSet.uint16(tag, i);
} else {
lut[i] = lutDataSet.byteArray[i + lutData.dataOffset];
}
}
return lut;
}
function populateSmallestLargestPixelValues(dataSet, imagePixelModule) {
const pixelRepresentation = dataSet.uint16('x00280103');
if (pixelRepresentation === 0) {
imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106');
imagePixelModule.largestPixelValue = dataSet.uint16('x00280107');
} else {
imagePixelModule.smallestPixelValue = dataSet.int16('x00280106');
imagePixelModule.largestPixelValue = dataSet.int16('x00280107');
}
imagePixelModule.largestPixelValue = imagePixelModule.largestPixelValue === 0 ? undefined : imagePixelModule.largestPixelValue;
}
function populatePaletteColorLut(dataSet, imagePixelModule) {
imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281101'
);
imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281102'
);
imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281103'
);
// The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
// When the number of table entries is equal to 2ˆ16 then this value shall be 0.
// See http://dicom.nema.org/MEDICAL/DICOM/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.5
if (imagePixelModule.redPaletteColorLookupTableDescriptor[0] === 0) {
imagePixelModule.redPaletteColorLookupTableDescriptor[0] = 65536;
imagePixelModule.greenPaletteColorLookupTableDescriptor[0] = 65536;
imagePixelModule.bluePaletteColorLookupTableDescriptor[0] = 65536;
}
// The third Palette Color Lookup Table Descriptor value specifies the number of bits for each entry in the Lookup Table Data.
// It shall take the value of 8 or 16.
// The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1.
// The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors.
//
// Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits;
// this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry.
// The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16.
const numLutEntries =
imagePixelModule.redPaletteColorLookupTableDescriptor[0];
const lutData = dataSet.elements.x00281201;
const lutBitsAllocated = lutData.length === numLutEntries ? 8 : 16;
// If the descriptors do not appear to have the correct values, correct them
if (
imagePixelModule.redPaletteColorLookupTableDescriptor[2] !==
lutBitsAllocated
) {
imagePixelModule.redPaletteColorLookupTableDescriptor[2] = lutBitsAllocated;
imagePixelModule.greenPaletteColorLookupTableDescriptor[2] =
lutBitsAllocated;
imagePixelModule.bluePaletteColorLookupTableDescriptor[2] =
lutBitsAllocated;
}
imagePixelModule.redPaletteColorLookupTableData = getLutData(
dataSet,
'x00281201',
imagePixelModule.redPaletteColorLookupTableDescriptor
);
imagePixelModule.greenPaletteColorLookupTableData = getLutData(
dataSet,
'x00281202',
imagePixelModule.greenPaletteColorLookupTableDescriptor
);
imagePixelModule.bluePaletteColorLookupTableData = getLutData(
dataSet,
'x00281203',
imagePixelModule.bluePaletteColorLookupTableDescriptor
);
}
function metaDataProvider(type, imageId) {
const parsedImageId = parseImageId(imageId);
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
@@ -99,5 +201,52 @@ function metaDataProvider(type, imageId) {
columnPixelSpacing,
};
}
if (type === 'imagePixelModule') {
const imagePixelModule = {
samplesPerPixel: dataSet.uint16('x00280002'),
photometricInterpretation: dataSet.string('x00280004'),
rows: dataSet.uint16('x00280010'),
columns: dataSet.uint16('x00280011'),
bitsAllocated: dataSet.uint16('x00280100'),
bitsStored: dataSet.uint16('x00280101'),
highBit: dataSet.uint16('x00280102'),
pixelRepresentation: dataSet.uint16('x00280103'),
planarConfiguration: dataSet.uint16('x00280006'),
pixelAspectRatio: dataSet.string('x00280034'),
};
populateSmallestLargestPixelValues(dataSet, imagePixelModule);
if (
imagePixelModule.photometricInterpretation === 'PALETTE COLOR' &&
dataSet.elements.x00281101
) {
populatePaletteColorLut(dataSet, imagePixelModule);
}
return imagePixelModule;
}
// if (type === 'imagePixelModule') {
// return {
// samplesPerPixel: dataSet.uint16('x00280002'),
// photometricInterpretation: dataSet.string('x00280004'),
// rows: dataSet.uint16('x00280010'),
// columns: dataSet.uint16('x00280011'),
// bitsAllocated: dataSet.uint16('x00280100'),
// bitsStored: dataSet.uint16('x00280101'),
// highBit: dataSet.uint16('x00280102'),
// pixelRepresentation: dataSet.uint16('x00280103'),
// planarConfiguration: dataSet.uint16('x00280006'),
// pixelAspectRatio: dataSet.uint16('x00280034'),
// smallestPixelValue: null,
// largestPixelValue: null,
// // smallestPixelValue: dataSet.uint16('x00280106'),
// // largestPixelValue: dataSet.uint16('x00280107'),
// redPaletteColorLookupTableDescriptor: dataSet.string('x00281101'),
// greenPaletteColorLookupTableDescriptor: dataSet.string('x00281102'),
// bluePaletteColorLookupTableDescriptor: dataSet.string('x00281103'),
// redPaletteColorLookupTableData: dataSet.string('x00281201'),
// greenPaletteColorLookupTableData: dataSet.string('x00281202'),
// bluePaletteColorLookupTableData: dataSet.string('x00281203')
// }
// }
}
export default metaDataProvider;
+1 -1
View File
@@ -445,7 +445,7 @@ function setTimer() {
totalBytes = totalBytes / 1024;
unit = "MB/s";
}
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit;
store.state.trials.uploadTip = totalBytes.toFixed(3) + unit;
}
if (timeList.length >= 5) {
delete bytesReceivedPerSecond[timeList[0]]
+1 -1
View File
@@ -150,7 +150,7 @@ function setTimer() {
totalBytes = totalBytes / 1024;
unit = "MB/s";
}
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit;
store.state.trials.uploadTip = totalBytes.toFixed(3) + unit;
}
if (timeList.length >= 5) {
delete bytesReceivedPerSecond[timeList[0]]
+1
View File
@@ -9,6 +9,7 @@ const ROUTER = require('@/router');
axios.defaults.withCredentials = false
const service = axios.create({
baseURL: '/api',
// baseURL: process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api',
timeout: 2 * 360000, // request timeout
withCredentials: false
})
@@ -18,7 +18,6 @@
</div>
</div>
<el-form-item
v-for="qs in questions"
v-show="qs.ShowQuestion!==2"
@@ -45,41 +44,41 @@
</template>
</el-input>
<!-- 测量 -->
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && !questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && !questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
@click="addAnnotation(qs)"
>
{{$t('trials:MRIPDFF:button:measure')}}
{{ $t('trials:MRIPDFF:button:measure') }}
</el-button>
<!-- 清除标记 -->
<el-button
v-if="getAnnotationStatus(qs) && readingTaskState!== 2"
size="mini"
type="text"
@click="removeAnnotation(qs)"
<el-button
v-if="getAnnotationStatus(qs) && readingTaskState!== 2"
size="mini"
type="text"
style="margin-left: 0px"
@click="removeAnnotation(qs)"
>
{{$t('trials:MRIPDFF:button:clear')}}
{{ $t('trials:MRIPDFF:button:clear') }}
</el-button>
<!-- 返回 -->
<el-button
v-if="questionForm[qs.Id]"
size="mini"
type="text"
@click="locateAnnotation(qs)"
<el-button
v-if="questionForm[qs.Id]"
size="mini"
type="text"
style="margin-left: 0px"
@click="locateAnnotation(qs)"
>
{{$t('trials:MRIPDFF:button:return')}}
{{ $t('trials:MRIPDFF:button:return') }}
</el-button>
<!-- 保存 -->
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
@click="saveAnnotation(qs)"
<el-button
v-if="questionForm[isMeasurableId] && parseInt(questionForm[isMeasurableId]) === 1 && questionForm[qs.Id] && readingTaskState!== 2"
size="mini"
type="text"
style="margin-left: 0px"
@click="saveAnnotation(qs)"
>
<!-- 未保存 -->
<el-tooltip v-if="getAnnotationSaveEnum(qs) === 0" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
@@ -279,7 +278,7 @@ export default {
},
mounted() {
this.trialId = this.$route.query.trialId
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.initForm()
DicomEvent.$on('handleImageQualityAbnormal', () => {
@@ -295,26 +294,29 @@ export default {
this.isMeasurableId = this.getQuestionId(1105)
// const loading = this.$loading({ fullscreen: true })
this.questions.forEach(item => {
var val = this.answers[item.Id]
if (item.DictionaryCode) {
val = isNaN(parseInt(this.answers[item.Id])) ? this.answers[item.Id] : parseInt(this.answers[item.Id])
if (this.answers.hasOwnProperty(item.Id)) {
let val = this.answers[item.Id]
if (item.DictionaryCode) {
val = isNaN(parseInt(this.answers[item.Id])) ? this.answers[item.Id] : parseInt(this.answers[item.Id])
}
this.$set(this.questionForm, item.Id, val)
} else {
this.$set(this.questionForm, item.Id, '')
}
this.$set(this.questionForm, item.Id, val)
})
this.$set(this.questionForm, 'MeasureData', this.answers.MeasureData ? JSON.parse(this.answers.MeasureData) : '')
this.$set(this.questionForm, 'RowIndex', this.answers.RowIndex ? this.answers.RowIndex : '')
this.$set(this.questionForm, 'RowId', this.answers.RowId ? this.answers.RowId : '')
// 如果存在标记且是否可测量为否,则将是否可测量更改为是
if (this.isCurrentTask && this.readingTaskState < 2) {
let arr = JSON.parse(this.answers.TableQuestionMarkList)
let isExitsMarks = arr.findIndex(i=>i.MeasureData) > -1
const arr = JSON.parse(this.answers.TableQuestionMarkList)
const isExitsMarks = arr.findIndex(i => i.MeasureData) > -1
if (isExitsMarks && parseInt(this.questionForm[this.isMeasurableId]) === 0) {
this.$set(this.questionForm, this.isMeasurableId, 1)
}
}
// saveTypeEnum 0:未保存过(新建病灶);1:已保存,信息不完整(随访初始化病灶/分裂病灶,通过状态判断);2:已保存,信息完整
let isMeasurable = this.getQuestionVal(1105)
const isMeasurable = this.getQuestionVal(1105)
const mean = this.getQuestionVal(1104)
if (this.questionForm.saveTypeEnum !== 1 && this.isCurrentTask && this.readingTaskState < 2) {
this.$set(this.questionForm, 'saveTypeEnum', parseInt(isMeasurable) === 1 && isNaN(parseFloat(mean)) ? 1 : 2)
@@ -325,11 +327,11 @@ export default {
this.markList = []
this.isExitsMarks = false
this.isDisabledMeasurableRadio = false
let seg = this.getQuestionVal(1106)
const seg = this.getQuestionVal(1106)
this.liverSeg = this.$fd('LiverSegmentation', seg)
if (this.answers.TableQuestionMarkList) {
let arr = JSON.parse(this.answers.TableQuestionMarkList)
arr.map(i=>{
const arr = JSON.parse(this.answers.TableQuestionMarkList)
arr.map(i => {
if (i.MeasureData) {
this.isExitsMarks = true
if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1 && this.isCurrentTask && this.readingTaskState < 2) {
@@ -337,15 +339,15 @@ export default {
}
i.MeasureData = JSON.parse(i.MeasureData)
}
this.markList.push({tableQuestionId: i.TableQuestionId, measureData: i, saveEnum: 1})
this.markList.push({ tableQuestionId: i.TableQuestionId, measureData: i, saveEnum: 1 })
})
}
let newMean = this.getMean()
const newMean = this.getMean()
if (newMean !== mean) {
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '')
}
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean || '')
}
if (this.questionForm.saveTypeEnum === 1 && this.isCurrentTask && this.readingTaskState < 2) {
this.setQuestions()
}
@@ -357,13 +359,13 @@ export default {
// I II III IV V VI VII VIII
// L-I-01 L-I-02 L-I-03
// L-II-01 L-II-02 L-II-03
let segArr = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII']
const segArr = ['I', 'II', 'III', 'IV', 'V', 'VI', 'VII', 'VIII']
let lessionName = ''
let segmentId = this.getQuestionId(1106)
const segmentId = this.getQuestionId(1106)
let segmentVal = this.answers[segmentId]
segmentVal = segmentVal ? parseInt(segmentVal) : null
if (segmentVal) {
let i = questionMark === 1101 ? '01' : questionMark === 1102 ? '02' : questionMark === 1103 ? '03' : ''
const i = questionMark === 1101 ? '01' : questionMark === 1102 ? '02' : questionMark === 1103 ? '03' : ''
lessionName = `${orderMark}-${segArr[segmentVal - 1]}-${i}`
}
return lessionName
@@ -397,18 +399,18 @@ export default {
this.$set(this.questionForm, 'saveTypeEnum', 1)
const mean = this.getQuestionVal(1104)
if (qs.QuestionMark === 1101 || qs.QuestionMark === 1102 || qs.QuestionMark === 1103) {
let newMean = this.getMean()
const newMean = this.getMean()
if (newMean !== mean) {
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '')
}
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean || '')
}
} else if (qs.QuestionMark === 1105) {
if (!v) {
let meanId = this.getQuestionId(1104)
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE')
} else {
let mean = this.getMean()
let meanId = this.getQuestionId(1104)
const mean = this.getMean()
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, mean)
}
}
@@ -418,10 +420,10 @@ export default {
let mean = null
let isMeasurable = this.getQuestionVal(1105)
isMeasurable = !isNaN(parseInt(isMeasurable)) ? parseInt(isMeasurable) : null
let l1 = this.getQuestionVal(1101)
let l2 = this.getQuestionVal(1102)
let l3 = this.getQuestionVal(1103)
if ( isMeasurable && !isNaN(parseFloat(l1)) && !isNaN(parseFloat(l2)) && !isNaN(parseFloat(l3))) {
const l1 = this.getQuestionVal(1101)
const l2 = this.getQuestionVal(1102)
const l3 = this.getQuestionVal(1103)
if (isMeasurable && !isNaN(parseFloat(l1)) && !isNaN(parseFloat(l2)) && !isNaN(parseFloat(l3))) {
const sum = l1 + l2 + l3
mean = sum / 3
return parseFloat(mean.toFixed(this.digitPlaces))
@@ -442,7 +444,7 @@ export default {
// 维护标记信息
measureData.data.remark = this.getLesionName(this.orderMark, this.activeQuestionMark)
}
let val = measureData.data.cachedStats.mean / 10
const val = measureData.data.cachedStats.mean / 10
this.$set(this.questionForm, measureData.tableQuestionId, val.toFixed(this.digitPlaces))
data = {
Id: '',
@@ -461,17 +463,17 @@ export default {
}
store.dispatch('reading/addMeasuredData', { visitTaskId: this.visitTaskId, data: data })
let mean = this.getQuestionVal(1104)
let newMean = this.getMean()
const newMean = this.getMean()
if (newMean !== mean) {
mean = newMean
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean ? newMean : '')
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, newMean || '')
}
const isMeasurable = this.getQuestionVal(1105)
DicomEvent.$emit('refreshStudyListMeasureData')
let i = this.markList.findIndex(i=>i.tableQuestionId === measureData.tableQuestionId)
const i = this.markList.findIndex(i => i.tableQuestionId === measureData.tableQuestionId)
if (i === -1) {
this.markList.push({tableQuestionId: measureData.tableQuestionId, measureData: data, saveEnum: 0})
this.markList.push({ tableQuestionId: measureData.tableQuestionId, measureData: data, saveEnum: 0 })
} else {
this.markList[i].saveEnum = 0
this.markList[i].measureData = data
@@ -486,19 +488,19 @@ export default {
},
addAnnotation(qs) {
// 判断是否有测量数据未保存
let i = this.markList.findIndex(i=>i.saveEnum === 0)
const i = this.markList.findIndex(i => i.saveEnum === 0)
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
this.$alert(this.$t('trials:MRIPDFF:message:message3'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message3'))
return
}
let orderMarkName = this.getLesionName(this.orderMark, qs.QuestionMark)
const orderMarkName = this.getLesionName(this.orderMark, qs.QuestionMark)
this.activeQuestionId = qs.Id
this.activeQuestionMark= qs.QuestionMark
DicomEvent.$emit('addAnnotation', {question: qs, locateInfo: { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: orderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true }})
this.activeQuestionMark = qs.QuestionMark
DicomEvent.$emit('addAnnotation', { question: qs, locateInfo: { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: orderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true }})
},
getAnnotationSaveEnum(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
if (i > -1) {
return this.markList[i].saveEnum
} else {
@@ -506,7 +508,7 @@ export default {
}
},
getAnnotationStatus(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
return true
} else {
@@ -516,14 +518,13 @@ export default {
getIsExitsMarks() {
const isMeasurable = this.getQuestionVal(1105)
if (!isNaN(parseInt(isMeasurable)) && parseInt(isMeasurable) === 1) {
return this.markList.findIndex(i=>i.measureData && i.measureData.MeasureData) > -1 ? true : false
return this.markList.findIndex(i => i.measureData && i.measureData.MeasureData) > -1
} else {
return false
}
},
async removeAnnotation(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
DicomEvent.$emit('imageLocation', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: this.markList[i].measureData.OrderMarkName, lesionType: null, markTool: 'Probe', readingTaskState: this.readingTaskState, isMarked: true })
// 是否确认清除标记?
const confirm = await this.$confirm(
@@ -534,27 +535,27 @@ export default {
}
)
if (confirm !== 'confirm') return
let measureData = Object.assign({}, this.markList[i].measureData)
const measureData = Object.assign({}, this.markList[i].measureData)
if (measureData.Id) {
await deleteSingleTableQuestionMark({Id: measureData.Id}, 11)
await deleteSingleTableQuestionMark({ Id: measureData.Id }, 11)
}
// 移除缓存中的measureData
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: measureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: measureData.OrderMarkName})
await store.dispatch('reading/removeMeasuredData', { visitTaskId: this.visitTaskId, measureData: measureData, questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, orderMarkName: measureData.OrderMarkName })
DicomEvent.$emit('getMeasureData')
this.markList[i].measureData = null
this.markList[i].saveEnum = 0
// 清除测量值、清除平均值
this.$set(this.questionForm, this.markList[i].tableQuestionId, '')
let meanId = this.getQuestionId(1104)
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, '')
this.isDisabledMeasurableRadio = this.getIsExitsMarks()
this.$set(this.questionForm, 'saveTypeEnum', 1)
this.setQuestions()
},
locateAnnotation(qs) {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
let measureData = this.markList[i].measureData
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
const measureData = this.markList[i].measureData
// 定位
var markTool = 'Probe'
var readingTaskState = this.readingTaskState
@@ -569,18 +570,18 @@ export default {
async saveAnnotation(qs) {
const loading = this.$loading({ fullscreen: true })
try {
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
let params = {}
if (i > -1 && this.markList[i].measureData && this.markList[i].measureData.MeasureData) {
let measureData = this.markList[i].measureData.MeasureData
const measureData = this.markList[i].measureData.MeasureData
// 上传截图
DicomEvent.$emit('getScreenshots', { questionId: this.parentQsId, rowIndex: this.questionForm.RowIndex, visitTaskId: this.visitTaskId, lesionName: measureData.OrderMarkName, lesionType: null, isMarked: !!measureData }, async val => {
params = Object.assign({}, this.markList[i].measureData)
if (val) {
let pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
const pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, val)
params.PicturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
}
let tableQuestionId = this.markList[i].tableQuestionId
const tableQuestionId = this.markList[i].tableQuestionId
params.Answer = this.questionForm[tableQuestionId]
params.MeasureData = JSON.stringify(this.markList[i].measureData.MeasureData)
loading.close()
@@ -588,13 +589,13 @@ export default {
})
} else {
params = {
Answer: "",
Answer: '',
VisitTaskId: this.visitTaskId,
QuestionId: this.parentQsId,
InstanceId: '',
SeriesId: '',
StudyId: '',
MarkTool:'',
MarkTool: '',
PicturePath: '',
NumberOfFrames: 0,
MeasureData: '',
@@ -607,9 +608,7 @@ export default {
loading.close()
this.saveTableQuestionInfo(params, qs)
}
} catch(e) {
} catch (e) {
console.log(e)
loading.close()
}
@@ -617,16 +616,16 @@ export default {
async saveTableQuestionInfo(params, qs) {
const loading = this.$loading({ fullscreen: true })
try {
let res = await saveTableQuestionMark(params, 11)
const res = await saveTableQuestionMark(params, 11)
if (res.IsSuccess) {
// 保存后设置保存状态
let i = this.markList.findIndex(i=>i.tableQuestionId === qs.Id)
const i = this.markList.findIndex(i => i.tableQuestionId === qs.Id)
this.markList[i].saveEnum = 1
// 保存病灶
let j = this.markList.findIndex(i=>!(i.saveEnum === 1 && i.measureData && i.measureData.MeasureData))
const j = this.markList.findIndex(i => !(i.saveEnum === 1 && i.measureData && i.measureData.MeasureData))
if (j === -1) {
let answers = []
let reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
const answers = []
const reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
for (const k in this.questionForm) {
if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
@@ -634,7 +633,7 @@ export default {
}
}
}
let params = {
const params = {
questionId: this.parentQsId,
rowId: this.questionForm.RowId,
rowIndex: this.answers.RowIndex,
@@ -659,7 +658,7 @@ export default {
DicomEvent.$emit('setMeasuredToolsPassive')
loading.close()
}
} catch(e) {
} catch (e) {
console.log(e)
loading.close()
}
@@ -735,43 +734,43 @@ export default {
async handleSave() {
try {
const valid = await this.$refs.measurementForm.validate()
if (!valid) return
if (parseInt(this.questionForm[this.isMeasurableId]) === 1) {
if (!valid) return
if (parseInt(this.questionForm[this.isMeasurableId]) === 1) {
// 检验是否有标记为保存
let i = this.markList.findIndex(i=>i.saveEnum === 0)
if (i > -1) {
const i = this.markList.findIndex(i => i.saveEnum === 0)
if (i > -1) {
// 请先保存标注信息!
this.$alert(this.$t('trials:MRIPDFF:message:message1'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message1'))
return
}
} else {
this.$alert(this.$t('trials:MRIPDFF:message:message1'))
// this.$message.warning(this.$t('trials:MRIPDFF:message:message1'))
return
}
} else {
// 不可测量时,清空测量值,平均值
// '是否确认不可测量?'
const confirm = await this.$confirm(
this.$t('trials:MRIPDFF:message:message2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
let l1Id = this.getQuestionId(1101)
this.$set(this.questionForm, l1Id, '')
let l2Id = this.getQuestionId(1102)
this.$set(this.questionForm, l2Id, '')
let l3Id = this.getQuestionId(1103)
this.$set(this.questionForm, l3Id, '')
let meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE')
}
const loading = this.$loading({ fullscreen: true })
const confirm = await this.$confirm(
this.$t('trials:MRIPDFF:message:message2'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
const l1Id = this.getQuestionId(1101)
this.$set(this.questionForm, l1Id, '')
const l2Id = this.getQuestionId(1102)
this.$set(this.questionForm, l2Id, '')
const l3Id = this.getQuestionId(1103)
this.$set(this.questionForm, l3Id, '')
const meanId = this.getQuestionId(1104)
this.$set(this.questionForm, meanId, 'NE')
}
try {
const loading = this.$loading({ fullscreen: true })
try {
// let isResetMarks = this.markList.findIndex(i=>i.measureData && i.measureData.MeasureData) > -1 ? true : false
if (parseInt(this.questionForm[this.isMeasurableId]) === 0 && this.isExitsMarks) {
await deleteTableQuestionMark({rowId: this.questionForm.RowId}, 11)
await deleteTableQuestionMark({ rowId: this.questionForm.RowId }, 11)
this.markList.forEach(i => {
if (i.measureData && i.measureData.MeasureData) {
i.measureData = ''
@@ -19,12 +19,21 @@
class="dicom-desc"
style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
>
<el-tooltip class="item" effect="dark" :content="`${study.StudyCode} ${study.Description?study.Description:''} ${study.Modalities} (${study.SeriesCount})`" placement="right">
<div>
<span>{{ study.StudyCode }} {{ study.Description }}</span>
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span>
<div style="text-overflow: ellipsis;overflow: hidden;" v-if="!study.StudyName">
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span style="margin-left: 5px;">{{ study.Modalities }} ({{ study.SeriesCount }})</span>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" v-else>
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName" style="margin: 0 5px">
{{study.StudyName}}
</span>
<div>{{ study.Modalities }} ({{ study.SeriesCount }})</div>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" :title="study.Description">{{ study.Description }}</div>
</div>
</el-tooltip>
</div>
</template>
@@ -205,7 +214,8 @@ export default {
srDialogVisible: false,
srInfo: {},
digitPlaces: 2,
visitTaskIdx: -1
visitTaskIdx: -1,
taskInfo: null
}
},
@@ -243,6 +253,7 @@ export default {
this.subjectCode = localStorage.getItem('subjectCode')
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
@@ -76,7 +76,7 @@
<el-input
v-if="question.Type==='input'"
v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2"
:disabled="question.TableQuestionType === 2 || readingTaskState === 2"
/>
<!-- 多行文本输入框 -->
<el-input
@@ -84,13 +84,14 @@
v-model="questionForm[question.Id]"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="readingTaskState === 2"
/>
<!-- 下拉框 -->
<el-select
v-if="question.Type==='select'"
v-model="questionForm[question.Id]"
clearable
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode"
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode || readingTaskState === 2"
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.TableQuestionType === 1">
@@ -132,6 +133,7 @@
v-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
@change="((val)=>{formItemChange(val, question)})"
:disabled="readingTaskState === 2"
>
<el-radio
v-for="val in question.TypeValue.split('|')"
@@ -145,6 +147,7 @@
<el-checkbox-group
v-if="question.Type==='checkbox'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState === 2"
>
<el-checkbox
v-for="val in question.TypeValue.split('|')"
@@ -158,12 +161,12 @@
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
@change="(val) => { formItemChange(val, question) }"
>
<el-option
@@ -176,7 +179,7 @@
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
@@ -190,7 +193,7 @@
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 4"
type="number"
:disabled="!question.ClassifyEditType"
:disabled="!question.ClassifyEditType || readingTaskState === 2"
v-model="questionForm[question.Id]"
@change="(val) => { formItemNumberChange(val, question) }"
/>
@@ -215,6 +218,7 @@
v-model="questionForm[question.Id]"
clearable
@change="(val) => { formItemNumberChange(val, question) }"
:disabled="readingTaskState === 2"
>
<el-option
v-for="val in question.TypeValue.split('|')"
@@ -229,6 +233,7 @@
@change="(val) => { formItemNumberChange(val, question) }"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
v-model="questionForm[question.Id]"
:disabled="readingTaskState === 2"
>
<!-- <template slot="append">1</template> -->
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
@@ -238,7 +243,7 @@
type="number"
v-if="question.Type === 'number' && !question.TypeValue && question.DataSource === 1"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
:disabled="question.DataSource === 1"
:disabled="question.DataSource === 1 || readingTaskState === 2"
v-model="questionForm[question.Id]"
>
<!-- <template slot="append">2</template> -->
@@ -248,6 +253,7 @@
<!-- 上传图像 -->
<el-upload
v-if="question.Type==='upload'"
:disabled="readingTaskState === 2"
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
@@ -258,7 +264,7 @@
:file-list="fileList"
:class="{disabled:question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}"
>
<el-button slot="default" class="el-icon-plus">
<el-button slot="default" class="el-icon-plus" v-if="readingTaskState < 2">
{{this.$t('common:button:upload')}}
</el-button>
</el-upload>
@@ -337,16 +343,37 @@
</el-button>
</template>
</base-model>
<!-- 预览文件 -->
<el-dialog
v-if="previewVisible"
:visible.sync="previewVisible"
:title="$t('common:button:preview')"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<div
class="base-modal-body"
style="border: 2px solid #ccc; padding: 10px"
>
<PreviewFile
v-if="previewVisible"
:file-path="currentPath"
:file-type="currentType"
/>
</div>
</el-dialog>
</div>
</template>
<script>
import { uploadReadingAnswerImage, getTrialOrganList, deleteReadingRowAnswer, getCustomTableQuestionPreview, getQuestionCalculateRelation, submitTableQuestion } from '@/api/trials'
import QuestionTableFormItem from './CustomizeQuestionTableFormItem'
import BaseModel from '@/components/BaseModel'
import PreviewFile from '@/components/PreviewFile/index'
import DicomEvent from './../components/DicomEvent'
export default {
name: 'CustomizeQuestionFormItem',
components: { QuestionTableFormItem, BaseModel },
components: { QuestionTableFormItem, BaseModel, PreviewFile },
props: {
IsBaseline: {
type: Boolean,
@@ -398,7 +425,10 @@ export default {
RowId: null,
digitPlaces: 2,
CalculationTabelList: [],
classArr: []
classArr: [],
previewVisible: false,
currentPath: '',
currentType: ''
}
},
watch: {
@@ -422,6 +452,13 @@ export default {
this.formItemNumberChange(this.question.Id, false)
}
},
readingTaskState: {
deep: true,
immediate: true,
handler(v, oldv) {
console.log(v)
}
}
},
mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
@@ -547,6 +584,7 @@ export default {
this.$set(this.QuestionsForm, obj.key, null)
},
handleSave() {
console.log('tableQsForm')
this.$refs.tableQsForm.validate(valid => {
if (!valid) return
const loading = this.$loading({ fullscreen: true })
@@ -612,6 +650,7 @@ export default {
var index = this.AnswersList.findIndex(v => v.RowId === this.QuestionsForm.RowId)
this.AnswersList.splice(index, 1, this.QuestionsForm)
}
console.log({key: this.question.Id, val: this.AnswersList, question: this.question})
this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question})
this.formItemNumberChange(this.question.Id, true)
this.addOrEdit.visible = false
@@ -935,7 +974,8 @@ export default {
let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file)
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}`, url: this.$getObjectName(res.url) })
this.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
this.$emit("setFormItemData", { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
this.$set(this.QuestionsForm, this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '')
loading.close()
// uploadReadingAnswerImage(this.$route.query.trialId, this.visitTaskId, formData).then(res => {
// if (res.IsSuccess) {
@@ -972,7 +1012,10 @@ export default {
var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
// window.open(this.OSSclientConfig.basePath + file.url,'_blank')
this.currentPath = file.url
this.currentType = suffix
this.previewVisible = true
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true
@@ -986,8 +1029,12 @@ export default {
if (file && file.status === "success") {
this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.fileList.forEach((i,index)=>{
i.name = `${this.$t('trials:emailManageCfg:title:fileName')}${index+ 1}`
})
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
this.$set(this.QuestionsForm, this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '')
}
}
}
@@ -77,6 +77,7 @@ export default {
methods: {
handleSave(isMsg) {
return new Promise(resolve => {
console.log('handleSave')
this.$refs['questions'].validate((valid) => {
if (!valid) {
resolve(false)
@@ -232,7 +233,9 @@ export default {
this.questionForm[v] = ''
},
setFormItemData(obj) {
console.log('setFormItemData', obj)
this.$set(this.questionForm, obj.key, JSON.parse(JSON.stringify(obj.val)))
console.log(this.questionForm)
this.classArr.map(i=>{
if (i.triggerId === obj.key) {
let answer = null
@@ -194,7 +194,7 @@
</template>
</template>
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.Type === 'upload'">
<CustomizeReportPageUpload
<customize-report-page-upload
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
:visitTaskId="visitTaskId"
:question="scope.row"
@@ -202,8 +202,8 @@
:readingTaskState="readingTaskState"
:initUrl="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}"
></CustomizeReportPageUpload>
<CustomizeReportPageUpload
></customize-report-page-upload>
<customize-report-page-upload
v-else-if="scope.row.Type==='upload'"
:visitTaskId="visitTaskId"
:question="scope.row"
@@ -211,25 +211,25 @@
:readingTaskState="readingTaskState"
:initUrl="questionForm[scope.row.QuestionId]"
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
></CustomizeReportPageUpload>
></customize-report-page-upload>
</template>
<template v-else-if="scope.row.Type === 'upload'">
<CustomizeReportPageUpload
<customize-report-page-upload
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
:visitTaskId="visitTaskId"
:question="scope.row"
:task="task"
:readingTaskState="readingTaskState"
:initUrl="scope.row.Answers[task.VisitTaskId]"
></CustomizeReportPageUpload>
<CustomizeReportPageUpload
></customize-report-page-upload>
<customize-report-page-upload
v-else-if="scope.row.Type==='upload'"
:visitTaskId="visitTaskId"
:question="scope.row"
:task="task"
:readingTaskState="readingTaskState"
:initUrl="scope.row.Answers[task.VisitTaskId]"
></CustomizeReportPageUpload>
></customize-report-page-upload>
</template>
<template v-else-if="scope.row.QuestionType=== 22">
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }}
@@ -276,6 +276,7 @@
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import { getAutoCutNextTask } from '@/api/user'
import DicomEvent from './../components/DicomEvent'
import CustomizeReportPageUpload from './CustomizeReportPageUpload'
import const_ from '@/const/sign-code'
@@ -736,15 +737,16 @@ export default {
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
submitDicomVisitTask(params).then(res => {
try {
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
let res = await submitDicomVisitTask(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) {
@@ -752,41 +754,36 @@ export default {
}
this.signVisible = false
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
//
this.readingTaskState = 2
store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
DicomEvent.$emit('setReadingState', 2)
window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
const res = await getAutoCutNextTask()
let isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
window.location.reload()
} else {
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
// var token = getToken()
// var subjectCode = this.$router.currentRoute.query.subjectCode
// var subjectId = this.$router.currentRoute.query.subjectId
// var trialId = this.$router.currentRoute.query.trialId
// this.$router.push({
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
// })
// DicomEvent.$emit('getNextTask')
window.location.reload()
})
.catch(action => {
})
}
}
this.loading = false
}).catch(() => {
} catch(e) {
this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false
}
})
}
},
previewDicoms(task) {
var token = getToken()
@@ -19,12 +19,20 @@
class="dicom-desc"
style="width: 150px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;"
>
<el-tooltip class="item" effect="dark" :content="`${study.StudyCode} ${study.Description?study.Description:''} ${study.Modalities} (${study.SeriesCount})`" placement="right">
<div>
<span>{{ study.StudyCode }} {{ study.Description }}</span>
<span> {{ study.Modalities }} ({{ study.SeriesCount }})</span>
<div>
<div style="text-overflow: ellipsis;overflow: hidden;" v-if="!study.StudyName">
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span>{{ study.Modalities }} ({{ study.SeriesCount }})</span>
</div>
</el-tooltip>
<div style="text-overflow: ellipsis;overflow: hidden;" v-else>
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName">
{{study.StudyName}}
</span>
<div>{{ study.Modalities }} ({{ study.SeriesCount }})</div>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;" :title="study.Description">{{ study.Description }}</div>
</div>
</div>
</template>
@@ -212,7 +220,8 @@ export default {
srDialogVisible: false,
srInfo: {},
digitPlaces: 2,
visitTaskIdx: -1
visitTaskIdx: -1,
taskInfo: null
}
},
@@ -250,6 +259,7 @@ export default {
this.subjectCode = localStorage.getItem('subjectCode')
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
DicomEvent.$on('refreshStudyListMeasureData', () => {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.measureData = this.visitTaskList[idx].MeasureData
@@ -339,6 +339,7 @@ export default {
localStorage.setItem('CriterionType', res.Result.CriterionType)
localStorage.setItem('digitPlaces', res.Result.DigitPlaces)
localStorage.setItem('IsExistUnprocessedFeedback', res.Result.IsExistUnprocessedFeedback)
localStorage.setItem('taskInfo', JSON.stringify(res.Result))
this.readingCategory = res.Result.ReadingCategory
this.questionFormChangeState = false
this.questionFormChangeNum = 0
@@ -66,7 +66,8 @@ export default function(evt) {
draw(context, context => {
// Configurable shadow
setShadow(context, this.configuration)
// Draw perpendicular line
const strokeWidth = lineWidth
const {
start,
end,
@@ -86,9 +87,6 @@ export default function(evt) {
// Draw the measurement line
drawLine(context, element, start, end, lineOptions)
// Draw perpendicular line
const strokeWidth = lineWidth
updatePerpendicularLineHandles(eventData, data)
drawLine(
@@ -10,9 +10,13 @@ const getNewContext = cornerstoneTools.import('drawing/getNewContext')
const draw = cornerstoneTools.import('drawing/draw')
const drawHandles = cornerstoneTools.import('drawing/drawHandles')
const drawTextBox = cornerstoneTools.import('drawing/drawTextBox')
const drawLink = cornerstoneTools.import('drawing/drawLink')
const drawLinkedTextBox = cornerstoneTools.import('drawing/drawLinkedTextBox')
// Utilities
const getRGBPixels = cornerstoneTools.import('util/getRGBPixels')
const calculateSUV = cornerstoneTools.import('util/calculateSUV')
const getROITextBoxCoords = cornerstoneTools.import('util/getROITextBoxCoords')
// import { probeCursor } from '../cursors/index.js';
// import { getLogger } from '../../util/logger.js';
const throttle = cornerstoneTools.import('util/throttle')
@@ -20,6 +24,8 @@ const getModule = cornerstoneTools.getModule
const getPixelSpacing = cornerstoneTools.import('util/getPixelSpacing')
// import numbersWithCommas from './../../util/numbersWithCommas.js';
const numbersWithCommas = cornerstoneTools.import('util/numbersWithCommas')
const clipBoxToDisplayedArea = cornerstoneTools.import('util/clip')
// const logger = getLogger('tools:annotation:ProbeTool');
import calculateEllipseStatistics from './calculateEllipseStatistics'
import getCircleCoords from './getCircleCoords'
@@ -31,6 +37,19 @@ import getCircleCoords from './getCircleCoords'
* desired position.
* @extends Tools.Base.BaseAnnotationTool
*/
const getHandle = (x, y, index, extraAttributes = {}) =>
Object.assign(
{
x,
y,
index,
drawnIndependently: false,
allowedOutsideImage: false,
highlight: true,
active: false
},
extraAttributes
)
export default class ProbeTool extends cornerstoneTools.ProbeTool {
constructor(props = {}) {
const defaultProps = {
@@ -64,7 +83,8 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
return;
}
const { x, y } = eventData.currentPoints.image
return {
visible: true,
active: true,
@@ -84,6 +104,23 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
active: true,
radius: 0
},
// textBox: {
// active: false,
// hasMoved: false,
// movesIndependently: false,
// drawnIndependently: true,
// allowedOutsideImage: true,
// hasBoundingBox: true,
// }
textBox: getHandle(x, y - 30, null, {
highlight: false,
hasMoved: true,
active: false,
movesIndependently: false,
drawnIndependently: true,
allowedOutsideImage: true,
hasBoundingBox: true
})
},
};
}
@@ -226,7 +263,7 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
draw(context, context => {
const color = toolColors.getColorIfActive(data);
const lineWidth = toolStyle.getToolWidth()
if (this.configuration.drawHandles) {
// Draw the handles
let radius = getCanvasRadius(data.handles, fixedRadius, element, pixelSpacing)
@@ -273,28 +310,133 @@ export default class ProbeTool extends cornerstoneTools.ProbeTool {
}
let r = getPixelRadius(fixedRadius, pixelSpacing)
// Coords for text
const coords = {
// Translate the x/y away from the cursor
x: data.handles.end.x + r,
y: data.handles.end.y - r,
};
const textCoords = external.cornerstone.pixelToCanvas(
eventData.element,
coords
);
drawTextBox(
if (!data.handles.hasOwnProperty('textBox')) {
const coords = {
// Translate the x/y away from the cursor
x: data.handles.end.x + r,
y: data.handles.end.y - r,
};
const textCoords = external.cornerstone.pixelToCanvas(
eventData.element,
coords
);
drawTextBox(
context,
textLines,
textCoords.x,
textCoords.y ,
color
);
return
}
// const handles = {
// start: {
// x: data.handles.end.x,
// y: data.handles.end.y
// },
// end: {
// x: data.handles.end.x + r,
// y: data.handles.end.y
// }
// }
let xOffset = 0
if (data.remark && !isNaN(parseInt(data.remark.slice(-1)))) {
let i = parseInt(data.remark.slice(-1))
if (i === 1) {
xOffset = -60
} else if (i === 2) {
xOffset = 0
} else if (i=== 3) {
xOffset = 0
}
}
// const xOffset = -30
const textBoxAnchorPoints = handles => [
handles.end
]
_drawLinkedTextBox(
context,
element,
data.handles.textBox,
textLines,
textCoords.x,
textCoords.y ,
color
);
// drawTextBox(context, '', textCoords.x, textCoords.y, color);
data.handles,
color,
lineWidth,
xOffset,
false
)
}
});
}
}
}
function _drawLinkedTextBox(
context,
element,
textBox,
text,
handles,
color,
lineWidth,
xOffset,
yCenter) {
const { pixelToCanvas } = external.cornerstone;
// Convert the textbox Image coordinates into Canvas coordinates
const textCoords = pixelToCanvas(element, textBox);
if (xOffset) {
textCoords.x += xOffset;
}
const options = {
centering: {
x: false,
y: yCenter,
},
};
options.displacer = box => clipBoxToDisplayedArea(element, box);
// Draw the text box
textBox.boundingBox = drawTextBox(
context,
text,
textCoords.x,
textCoords.y,
color,
options
);
if (textBox.hasMoved) {
// Identify the possible anchor points for the tool -> text line
let arr = [
{
x: handles.end.x,
y: handles.end.y
},
{
x: handles.end.x,
y: handles.end.y
}
]
const linkAnchorPoints = arr.map(h =>
pixelToCanvas(element, h)
);
// Draw dashed link line between tool and text
drawLink(
linkAnchorPoints,
textCoords,
textBox.boundingBox,
context,
color,
lineWidth
);
}
}
function _getUnit(modality, showHounsfieldUnits) {
return modality === 'CT' && showHounsfieldUnits !== false ? 'HU' : '';
}
@@ -3,30 +3,30 @@
<!-- 访视阅片 -->
<visit-review v-if="taskInfo && taskInfo.ReadingCategory=== 1" />
<!-- 全局阅片 -->
<global-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 2"
:trialId="trialId"
:subjectId="taskInfo.SubjectId"
:visitTaskId="taskInfo.VisitTaskId"
:readingCategory="taskInfo.ReadingCategory"
:subjectCode="taskInfo.SubjectCode"
:taskBlindName="taskInfo.TaskBlindName"
:isReadingShowSubjectInfo="taskInfo.IsReadingShowSubjectInfo"
:isReadingShowPreviousResults="taskInfo.IsReadingShowPreviousResults"
:isExistsClinicalData="taskInfo.IsExistsClinicalData"
<global-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 2"
:trial-id="trialId"
:subject-id="taskInfo.SubjectId"
:visit-task-id="taskInfo.VisitTaskId"
:reading-category="taskInfo.ReadingCategory"
:subject-code="taskInfo.SubjectCode"
:task-blind-name="taskInfo.TaskBlindName"
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
:is-reading-show-previous-results="taskInfo.IsReadingShowPreviousResults"
:is-exists-clinical-data="taskInfo.IsExistsClinicalData"
/>
<!-- 裁判阅片 -->
<ad-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 4"
:trialId="trialId"
:subjectId="taskInfo.SubjectId"
:visitTaskId="taskInfo.VisitTaskId"
:readingCategory="taskInfo.ReadingCategory"
:subjectCode="taskInfo.SubjectCode"
:taskBlindName="taskInfo.TaskBlindName"
:isReadingShowSubjectInfo="taskInfo.IsReadingShowSubjectInfo"
:isReadingShowPreviousResults="taskInfo.IsReadingShowPreviousResults"
:isExistsClinicalData="taskInfo.IsExistsClinicalData"
<ad-review
v-else-if="taskInfo && taskInfo.ReadingCategory=== 4"
:trial-id="trialId"
:subject-id="taskInfo.SubjectId"
:visit-task-id="taskInfo.VisitTaskId"
:reading-category="taskInfo.ReadingCategory"
:subject-code="taskInfo.SubjectCode"
:task-blind-name="taskInfo.TaskBlindName"
:is-reading-show-subject-info="taskInfo.IsReadingShowSubjectInfo"
:is-reading-show-previous-results="taskInfo.IsReadingShowPreviousResults"
:is-exists-clinical-data="taskInfo.IsExistsClinicalData"
/>
<!-- 肿瘤学阅片 -->
<!-- <oncology-review v-else-if="taskInfo && taskInfo.ReadingCategory=== 5" /> -->
@@ -60,7 +60,7 @@
</div>
</el-dialog>
</div>
</div>
</template>
<script>
import { getNextTask, readClinicalData } from '@/api/trials'
@@ -134,7 +134,7 @@ export default {
} catch (e) {
this.loading = false
}
},
}
}
}
</script>
@@ -148,7 +148,7 @@ export default {
height:80%;
}
::v-deep .el-dialog__body{
padding: 20px 20px 0 20px;
padding: 10px;
height: calc(100% - 70px);
}
.el-dialog__header{
@@ -0,0 +1,173 @@
<template>
<div>
<el-upload
action
:accept="question.FileType"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
:http-request="uploadScreenshot"
list-type="picture-card"
:on-remove="handleRemove"
:file-list="fileList"
:class="{disabled:readingTaskState >= 2 || (question.ImageCount === 0 ? false : fileList.length >= question.ImageCount) || (task.VisitTaskId !== visitTaskId) || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))}"
:disabled="readingTaskState >= 2 || task.VisitTaskId !== visitTaskId || question.IsShowInDicom || ((task.IsBaseLine && question.LimitEdit === 2) || (!task.IsBaseLine && question.LimitEdit === 1))"
>
<i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}">
<viewer
:ref="file.url"
:images="[imageUrl]"
style="
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
"
>
<img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
crossOrigin="anonymous"
alt=""
style="max-width: 100%; max-height: 100%"
/>
<span class="el-upload-list__item-actions">
<span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" />
</span>
<span
v-if="readingTaskState < 2"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete" />
</span>
</span>
</viewer>
</div>
</el-upload>
</div>
</template>
<script>
import { uploadReadingAnswerImage, getTrialOrganList, getCustomTableQuestionPreview } from '@/api/trials'
export default {
name: "CustomizeReportPageUpload",
props: {
task: {
Type: Object,
required: true
},
question: {
Type: Object,
required: true
},
visitTaskId: {
type: String,
required: true
},
readingTaskState: {
type: Number,
required: true
},
initUrl: {
type: String,
default: ''
}
},
data () {
return {
imgVisible: false,
imageUrl: null,
accept: '.png,.jpg,.jpeg',
fileList: [],
}
},
mounted() {
this.urls = this.initUrl === '' ? [] : this.initUrl.split('|')
console.log(this.visitTaskId, this.urls)
this.fileList = []
this.urls.map(url => {
this.fileList.push({ name: '', url: `${url}` })
})
// console.log(this.fileList)
},
methods: {
checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length)
if (this.question.FileType.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false
} else {
return true
}
},
async uploadScreenshot(param) {
if (!this.visitTaskId) return
const loading = this.$loading({
target: document.querySelector('.ecrf-wrapper'),
fullscreen: false,
lock: true,
text: 'Loading',
spinner: 'el-icon-loading'
})
var trialId = this.$route.query.trialId
var subjectId = this.$route.query.trialId
var file = await this.fileToBlob(param.file)
const res = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${param.file.name}`, file)
console.log(res)
this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url)})
this.urls.push(this.$getObjectName(res.url))
this.$emit('setImageUrl', this.urls.length > 0 ? this.urls.join('|') : '')
loading.close()
},
handleBeforeUpload(file) {
//
if (this.checkFileSuffix(file.name)) {
// this.fileList = []
return true
} else {
// this.$alert(` ${this.accept} `)
let msg = this.$t(
"trials:readingUnit:qsList:message:imageFormat"
).replace("xxx", this.question.FileType)
this.$alert(msg)
return false
}
},
//
handlePictureCardPreview(file) {
var suffix = file.url.substring(file.url.lastIndexOf(".")+1)
suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf'){
window.open(this.OSSclientConfig.basePath + file.url,'_blank')
}else{
this.imageUrl = this.OSSclientConfig.basePath + file.url
// this.imgVisible = true
this.$refs[file.url].$viewer.show()
}
},
//
handleRemove(file, fileList) {
this.imageUrl = ''
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '' })
},
}
}
</script>
<style lang="scss" scoped>
.disabled{
::v-deep .el-upload--picture-card {
display: none;
}
}
</style>
@@ -1,12 +1,13 @@
<template>
<div v-loading="loading" class="ecrf-list-container">
<el-form
v-if="taskInfo"
ref="questions"
size="small"
:model="questionForm"
class="ecrf-form"
>
<FormItem
<!-- <FormItem
v-for="question of questions"
:key="question.Id"
:question="question"
@@ -16,6 +17,19 @@
:calculation-list="calculationList"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/> -->
<QuestionFormItem
v-for="question of questions"
:key="question.Id"
:visit-task-id="visitTaskId"
:question="question"
:question-form="questionForm"
:reading-task-state="readingTaskState"
:criterion-id="criterionId"
:calculation-list="calculationList"
:is-baseline="isBaseline"
@resetFormItemData="resetFormItemData"
@setFormItemData="setFormItemData"
/>
<el-form-item v-if="readingTaskState < 2">
@@ -53,17 +67,18 @@
<script>
import { getTrialReadingQuestion, saveVisitTaskQuestions, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
import const_ from '@/const/sign-code'
import store from '@/store'
import { mapGetters } from 'vuex'
import FormItem from './FormItem'
// import FormItem from './FormItem'
import QuestionFormItem from '@/views/trials/trials-panel/reading/dicoms/customize/CustomizeQuestionFormItem'
import SignForm from '@/views/trials/components/newSignForm'
export default {
name: 'EcrfList',
components: {
FormItem,
QuestionFormItem,
SignForm
},
props: {
@@ -88,7 +103,8 @@ export default {
activeName: 0,
classArr: [],
calculationList: [],
taskInfo: null
taskInfo: null,
isBaseline: false
}
},
computed: {
@@ -109,6 +125,7 @@ export default {
currentTaskState: {
immediate: true,
handler(state) {
console.log(state)
if (state === 2) {
this.readingTaskState = 2
}
@@ -117,45 +134,65 @@ export default {
},
mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.isBaseline = this.taskInfo.IsBaseLine
},
methods: {
async getQuestions() {
async getQuestions(visitTaskId) {
this.loading = true
try {
const param = {
readingQuestionCriterionTrialId: this.criterionId,
visitTaskId: this.visitTaskId
}
const res = await getTrialReadingQuestion(param)
const res = await getCustomTableQuestionAnswer(param)
if (res.IsSuccess) {
this.readingTaskState = res.OtherInfo.readingTaskState
this.readingTaskState = res.OtherInfo.ReadingTaskState
res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
this.$set(this.questionForm, v.Id, v.Answer ? v.Answer : null)
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.Id, v.Answer)
}
if (v.Type === 'table' || v.Type === 'basicTable') {
this.$set(this.questionForm, v.Id, v.TableQuestions.Answers)
}
if (v.Type === 'class') {
this.classArr.push({ triggerId: v.ClassifyQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType })
}
if (v.Type === 'number') {
this.$set(this.questionForm, v.Id, v.Answer === '' ? '' : parseFloat(v.Answer).toFixed(this.digitPlaces))
}
if (v.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.SinglePage
this.loading = false
}
this.loading = false
} catch (e) {
console.log(e)
this.loading = false
}
},
setChild(obj) {
obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, i.Answer ? i.Answer : null)
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, i.Id, i.Answer)
}
if (i.Type === 'table' || i.Type === 'basicTable') {
i.TableQuestions.Questions.forEach(o => {
if (o.Type === 'number') {
i.TableQuestions.Answers.forEach((ite, index) => {
this.$set(i.TableQuestions.Answers[index], o.Id, i.TableQuestions.Answers[index][o.Id] ? parseFloat(i.TableQuestions.Answers[index][o.Id]).toFixed(this.digitPlaces) : null)
})
}
})
this.$set(this.questionForm, i.Id, i.TableQuestions.Answers)
}
if (i.Type === 'class') {
this.classArr.push({ triggerId: i.ClassifyQuestionId, classId: i.Id, classifyAlgorithms: i.ClassifyAlgorithms, classifyType: i.ClassifyType })
}
if (i.Type === 'number') {
this.$set(this.questionForm, i.Id, i.Answer === '' ? '' : parseFloat(i.Answer).toFixed(this.digitPlaces))
}
if (i.Childrens && i.Childrens.length > 0) {
this.setChild(i.Childrens)
}
@@ -169,26 +206,28 @@ export default {
console.log(e)
}
},
async handleSave() {
async handleSave(isMsg) {
const valid = await this.$refs['questions'].validate()
if (!valid) return
this.loading = true
const answers = []
for (const k in this.questionForm) {
answers.push({ readingQuestionTrialId: k, answer: this.questionForm[k] })
}
const params = {
trialId: this.trialId,
visitTaskId: this.visitTaskId,
readingQuestionCriterionTrialId: this.criterionId,
answerList: answers
}
try {
const res = await saveVisitTaskQuestions(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
var answers = []
for (const k in this.questionForm) {
if (this.questionForm[k] instanceof Array) {} else {
answers.push({ id: k, answer: this.questionForm[k] })
}
}
var params = {
visitTaskId: this.visitTaskId,
answers: answers
}
const res = await changeDicomReadingQuestionAnswer(params)
if (res.IsSuccess) {
if (isMsg) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
this.loading = false
}
this.loading = false
} catch (e) {
this.loading = false
}
@@ -314,5 +353,50 @@ export default {
}
}
::v-deep .el-table,
.el-table__expanded-cell {
background-color: #000;
color: #fff;
border-color: #444444;
}
::v-deep .el-table th,
.el-table tr {
background-color: #000;
color: #fff;
border-color: #444444;
}
::v-deep .el-table__body tr > td {
background-color: #000 !important;
color: #fff;
border-color: #444444;
}
::v-deep .el-table__body tr:hover > td {
background-color: #858282 !important;
color: #fff;
border-color: #444444;
}
::v-deep .el-table--border th.gutter:last-of-type {
border: none;
}
::v-deep .el-dialog{
background: #1e1e1e;
border: 1px solid #ddd;
color: #ddd;
.el-dialog__title{
color:#fff;
}
.el-input .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
.el-input.is-disabled .el-input__inner{
background-color: #646464a1;
}
.el-form-item__label{
color: #dfdfdf
}
}
}
</style>
@@ -2,104 +2,110 @@
<div class="none-dicom-viewer">
<!-- tools -->
<div class="tools-wrapper">
<!-- 布局 -->
<div class="tool-item" :title="$t('trials:reading:button:layout')">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
<svg-icon icon-class="layout" class="svg-icon" /><i class="el-icon-arrow-down el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<!-- 缩放 -->
<div
:class="['tool-item', activeTool === 'Zoom' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:zoom')"
@click.prevent="setToolActive('Zoom')"
>
<svg-icon icon-class="magnifier" class="svg-icon" />
</div>
<!-- 移动 -->
<div
:class="['tool-item', activeTool === 'Pan' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:move')"
@click.prevent="setToolActive('Pan')"
>
<svg-icon icon-class="move" class="svg-icon" />
</div>
<!-- 旋转 -->
<div
:class="['tool-item', activeTool === 'PlanarRotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:rotate')"
@click.prevent="setToolActive('PlanarRotate')"
>
<svg-icon icon-class="rotate" class="svg-icon" />
</div>
<!-- 箭头工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'ArrowAnnotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:arrowAnnotate')"
@click.prevent="setAnnotateToolActive('ArrowAnnotate')"
>
<svg-icon icon-class="arrow" class="svg-icon" />
</div>
<!-- 矩形工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'RectangleROI' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:RectangleRoi')"
@click.prevent="setAnnotateToolActive('RectangleROI')"
>
<svg-icon icon-class="rectangle" class="svg-icon" />
</div>
<!-- 自由曲线 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'PlanarFreehandROI' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:planarFreehandROI')"
@click.prevent="setAnnotateToolActive('PlanarFreehandROI')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</div>
<!-- <div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'SplineROITool' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:SplineROITool')"
@click.prevent="setAnnotateToolActive('SplineROITool')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</div> -->
<div class="tools-left">
<!-- 布局 -->
<div class="tool-item" :title="$t('trials:reading:button:layout')">
<el-dropdown @command="handleCommand">
<span class="el-dropdown-link">
<svg-icon icon-class="layout" class="svg-icon" /><i class="el-icon-arrow-down el-icon--right" />
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="1*1">1*1</el-dropdown-item>
<el-dropdown-item command="1*2">1*2</el-dropdown-item>
<el-dropdown-item command="2*2">2*2</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<!-- 缩放 -->
<div
:class="['tool-item', activeTool === 'Zoom' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:zoom')"
@click.prevent="setToolActive('Zoom')"
>
<svg-icon icon-class="magnifier" class="svg-icon" />
</div>
<!-- 移动 -->
<div
:class="['tool-item', activeTool === 'Pan' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:move')"
@click.prevent="setToolActive('Pan')"
>
<svg-icon icon-class="move" class="svg-icon" />
</div>
<!-- 旋转 -->
<div
:class="['tool-item', activeTool === 'PlanarRotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:rotate')"
@click.prevent="setToolActive('PlanarRotate')"
>
<svg-icon icon-class="rotate" class="svg-icon" />
</div>
<!-- 箭头工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'ArrowAnnotate' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:arrowAnnotate')"
@click.prevent="setAnnotateToolActive('ArrowAnnotate')"
>
<svg-icon icon-class="arrow" class="svg-icon" />
</div>
<!-- 矩形工具 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'RectangleROI' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:RectangleRoi')"
@click.prevent="setAnnotateToolActive('RectangleROI')"
>
<svg-icon icon-class="rectangle" class="svg-icon" />
</div>
<!-- 自由曲线 -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'PlanarFreehandROI' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:planarFreehandROI')"
@click.prevent="setAnnotateToolActive('PlanarFreehandROI')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</div>
<!-- <div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'SplineROITool' ? 'tool-item-active' : '']"
:title="$t('trials:reading:button:SplineROITool')"
@click.prevent="setAnnotateToolActive('SplineROITool')"
>
<svg-icon icon-class="polygon" class="svg-icon" />
</div> -->
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:Eraser')"
@click.prevent="setAnnotateToolActive('Eraser')"
>
<svg-icon icon-class="clear" class="svg-icon" />
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Eraser' ? 'tool-item-active' : '']"
:title="$t('trials:dicom-show:Eraser')"
@click.prevent="setAnnotateToolActive('Eraser')"
>
<svg-icon icon-class="clear" class="svg-icon" />
</div>
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Length' ? 'tool-item-active' : '']"
:title="$t('trials:nondicom-show:scale')"
@click.prevent="setAnnotateToolActive('Length')"
>
<svg-icon icon-class="length" class="svg-icon" />
</div>
<!-- 截图 -->
<!-- <div
class="tool-item"
:title="$t('trials:reading:button:screenShot')"
@click.prevent="saveImage"
>
<svg-icon icon-class="image" class="svg-icon" />
</div> -->
<!-- 重置 -->
<div
class="tool-item"
:title="$t('trials:reading:button:reset')"
@click.prevent="resetViewport"
>
<svg-icon icon-class="refresh" class="svg-icon" />
</div>
</div>
<div
:class="['tool-item', readingTaskState === 2 ? 'tool-disabled' : '', activeTool === 'Length' ? 'tool-item-active' : '']"
:title="$t('trials:nondicom-show:scale')"
@click.prevent="setAnnotateToolActive('Length')"
>
<svg-icon icon-class="length" class="svg-icon" />
</div>
<!-- 截图 -->
<!-- <div
class="tool-item"
:title="$t('trials:reading:button:screenShot')"
@click.prevent="saveImage"
>
<svg-icon icon-class="image" class="svg-icon" />
</div> -->
<!-- 重置 -->
<div
class="tool-item"
:title="$t('trials:reading:button:reset')"
@click.prevent="resetViewport"
>
<svg-icon icon-class="refresh" class="svg-icon" />
<div>
<el-button type="text" @click="previewConfig">{{ $t('trials:reading:button:customCfg') }}</el-button>
</div>
</div>
<!-- viewports -->
@@ -237,6 +243,16 @@
<el-button type="primary" @click="saveForm">{{ $t('common:button:save') }}</el-button>
</span>
</el-dialog>
<el-dialog
v-if="personalConfigDialog.visible"
:visible.sync="personalConfigDialog.visible"
:close-on-click-modal="false"
:title="personalConfigDialog.title"
width="600px"
>
<Others />
</el-dialog>
</div>
</template>
<script>
@@ -258,6 +274,7 @@ import hardcodedMetaDataProvider from './../js/hardcodedMetaDataProvider'
import registerWebImageLoader from './../js/registerWebImageLoader'
import { mapGetters } from 'vuex'
import store from '@/store'
import Others from '@/views/trials/trials-panel/reading/dicoms/components/Others'
const { ViewportType } = Enums
const renderingEngineId = 'myRenderingEngine'
const {
@@ -278,6 +295,7 @@ const {
const { MouseBindings, Events: toolsEvents } = csToolsEnums
export default {
name: 'ImageViewer',
components: { Others },
props: {
relatedStudyInfo: {
type: Object,
@@ -310,6 +328,7 @@ export default {
imageType: ['image/jpeg', 'image/jpg', 'image/bmp', 'image/png'],
digitPlaces: 2,
dialogVisible: false,
personalConfigDialog: { visible: false, title: this.$t('trials:reading:button:customCfg') }, //
form: {
length: null,
annotationObj: {}
@@ -1180,6 +1199,9 @@ export default {
//
viewCD(id) {
this.$emit('previewCD', id)
},
previewConfig() {
this.personalConfigDialog.visible = true
}
}
}
@@ -1194,11 +1216,17 @@ export default {
.tools-wrapper {
height: 50px;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
border-bottom: 1px solid #727272;
color: #ddd;
padding: 0 5px;
.tools-left {
flex: 1;
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
}
.tool-item {
padding: 5px;
margin: 0 5px;
@@ -1317,5 +1345,24 @@ export default {
}
}
}
::v-deep .el-dialog{
background: #1e1e1e;
border: 1px solid #ddd;
color: #ddd;
.el-dialog__title{
color:#fff;
}
.el-input .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
.el-input.is-disabled .el-input__inner{
background-color: #646464a1;
}
.el-form-item__label{
color: #dfdfdf
}
}
}
</style>
@@ -170,6 +170,13 @@
</span>
</div>
</template>
<template v-else-if="scope.row.Type==='upload' && scope.row.Answers[task.VisitTaskId]">
<span v-for="(url,index) in scope.row.Answers[task.VisitTaskId].split('|')" :key="url" style="margin-left: 5px;">
<el-button v-if="scope.row.Answers[task.VisitTaskId]" type="text" @click="preview(url)">
{{ `${$t('trials:noneDicom:title:attachment')}${index + 1}` }}
</el-button>
</span>
</template>
<template v-else-if="scope.row.DictionaryCode">
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
</template>
@@ -206,19 +213,41 @@
</div>
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
</el-dialog>
<!-- 预览文件 -->
<el-dialog
v-if="previewVisible"
:visible.sync="previewVisible"
:title="$t('common:button:preview')"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<div
class="base-modal-body"
style="border: 2px solid #ccc; padding: 10px"
>
<PreviewFile
v-if="previewVisible"
:file-path="currentPath"
:file-type="currentType"
/>
</div>
</el-dialog>
</div>
</template>
<script>
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
import { setSkipReadingCache } from '@/api/reading'
// import UploadFile from './UploadFile'
import { getAutoCutNextTask } from '@/api/user'
import const_ from '@/const/sign-code'
import SignForm from '@/views/trials/components/newSignForm'
import PreviewFile from '@/components/PreviewFile/index'
import { getToken } from '@/utils/auth'
import store from '@/store'
export default {
name: 'ReportPage',
components: { SignForm },
name: 'CustomizeReportPage',
components: { SignForm, PreviewFile },
data() {
return {
trialId: '',
@@ -242,7 +271,10 @@ export default {
tableAnswers: {},
questionForm: {},
questionId: null,
taskInfo: null
taskInfo: null,
previewVisible: false,
currentPath: '',
currentType: ''
}
},
watch: {
@@ -264,7 +296,8 @@ export default {
this.visitTaskId = this.taskInfo.VisitTaskId
this.subjectId = this.taskInfo.SubjectId
this.criterionType = this.taskInfo.CriterionType
this.digitPlaces = this.taskInfo.DigitPlaces
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.TrialReadingCriterionId = this.taskInfo.TrialReadingCriterionId
window.addEventListener('resize', () => {
this.handleResize()
@@ -351,11 +384,11 @@ export default {
},
InitVisitTaskQuestionForm() {
this.taskQuestions.map((v, i) => {
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'number') {
if (v.Type === 'group' && v.Childrens.length === 0 && v.Type !== 'table' && v.Type !== 'basicTable') return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary' && v.Type !== 'table' && v.Type !== 'basicTable' && v.Type !== 'number') {
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId])
}
if (v.Type === 'table') {
if (v.Type === 'table' || v.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(v.QuestionId, v.Childrens, i)
this.$set(this.questionForm, v.QuestionId, tableAnswers)
// this.$set(v, 'xfIndex', i)
@@ -379,10 +412,10 @@ export default {
},
setChild(obj) {
obj.forEach((i, index) => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table') {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id && i.Type !== 'table' && i.Type !== 'basicTable') {
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId])
}
if (i.Type === 'table') {
if (i.Type === 'table' || i.Type === 'basicTable') {
var tableAnswers = this.getTableAnswers(i.QuestionId, i.Childrens, index)
this.$set(this.questionForm, i.QuestionId, tableAnswers)
}
@@ -397,7 +430,7 @@ export default {
}
this.$set(this.questionForm, i.QuestionId, val)
}
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table') {
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table' && i.Type !== 'basicTable') {
this.setChild(i.Childrens)
}
})
@@ -450,19 +483,18 @@ export default {
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
break
case 8:
var arr = []
const arr = []
this.questionForm[o.QuestionId].forEach(q => {
arr.push(q[o.TableQuestionId])
})
num = arr.length === 0 ? 0 : Math.max(...arr)
break
case 9:
// eslint-disable-next-line no-redeclare
var arr = []
const arr1 = []
this.questionForm[o.QuestionId].forEach(q => {
arr.push(q[o.TableQuestionId])
arr1.push(q[o.TableQuestionId])
})
num = arr.length === 0 ? 0 : Math.min(...arr)
num = arr1.length === 0 ? 0 : Math.min(...arr1)
break
}
} else {
@@ -489,11 +521,10 @@ export default {
} catch (e) {
console.log(e)
}
var digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
if (rules.ValueType === 2) {
num = num * 100
}
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(digitPlaces) : '∞'
return isNaN(num) ? '' : isFinite(num) ? num.toFixed(this.digitPlaces) : '∞'
},
getReportInfo() {
this.loading = true
@@ -522,8 +553,6 @@ export default {
questions.forEach((item) => {
const obj = item
this.$set(obj, 'Answers', {})
var digitPlaces = parseInt(localStorage.getItem('digitPlaces')) || 0
item.Answer.forEach(i => {
if (item.DictionaryCode) {
this.$set(obj.Answers, i.VisitTaskId, i.Answer ? parseInt(i.Answer) : null)
@@ -536,7 +565,7 @@ export default {
} else if (item.ValueType === 3) {
val = i.Answer
} else {
val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(digitPlaces)
val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(this.digitPlaces)
}
this.$set(obj.Answers, i.VisitTaskId, val)
} else {
@@ -590,15 +619,16 @@ export default {
}
},
//
signConfirm(signInfo) {
async signConfirm(signInfo) {
this.loading = true
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
submitDicomVisitTask(params).then(res => {
try {
var params = {
data: {
visitTaskId: this.visitTaskId
},
signInfo: signInfo
}
const res = await submitDicomVisitTask(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
if (this.$refs['signForm']) {
@@ -606,43 +636,39 @@ export default {
}
this.signVisible = false
// window.location.reload()
// window.opener.postMessage('refreshTaskList', window.location)
//
this.readingTaskState = 2
this.taskInfo.ReadingTaskState = 2
localStorage.setItem('taskInfo', JSON.stringify(this.taskInfo))
store.dispatch('noneDicomReview/setCurrentTaskState', 2)
// DicomEvent.$emit('setReadingState', 2)
window.opener.postMessage('refreshTaskList', window.location)
this.$confirm(this.$t('trials:oncologyReview:title:msg2'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
// var token = getToken()
// var subjectCode = this.$router.currentRoute.query.subjectCode
// var subjectId = this.$router.currentRoute.query.subjectId
// var trialId = this.$router.currentRoute.query.trialId
// this.$router.push({
// path: `/readingPage?subjectCode=${subjectCode}&subjectId=${subjectId}&trialId=${trialId}&TokenKey=${token}`
// })
// DicomEvent.$emit('getNextTask')
window.location.reload()
})
.catch(action => {
const res = await getAutoCutNextTask()
const isAutoTask = res.Result.AutoCutNextTask
if (isAutoTask) {
window.location.reload()
} else {
// ''
this.$confirm(this.$t('trials:readingReport:message:msg4'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
window.location.reload()
})
.catch(action => {
// changeURLStatic('visitTaskId', this.visitTaskId)
})
}
}
this.loading = false
}).catch(() => {
} catch (e) {
console.log(e)
this.loading = false
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
this.$refs['signForm'].btnLoading = false
}
})
}
},
previewDicoms(task) {
var token = getToken()
@@ -721,6 +747,13 @@ export default {
this.loading = false
console.log(e)
}
},
//
preview(path) {
this.currentPath = path
const arr = path.split('.')
this.currentType = arr[arr.length - 1]
this.previewVisible = true
}
}
}
@@ -787,6 +820,28 @@ export default {
height: 30px;
line-height: 40px;
}
::v-deep .el-dialog{
background: #1e1e1e;
border: 1px solid #ddd;
color: #ddd;
.el-dialog__title{
color:#fff;
}
.el-input .el-input__inner{
background-color: transparent;
color: #ddd;
border: 1px solid #5e5e5e;
}
.el-input.is-disabled .el-input__inner{
background-color: #646464a1;
}
.el-form-item__label{
color: #dfdfdf
}
}
}
::v-deep .el-switch__label{
color:#fff;
}
::v-deep .el-switch__label.is-active{
color: #428bca;
@@ -22,8 +22,12 @@
v-if="!study.IsCriticalSequence"
class="dicom-desc"
>
<div>{{ study.CodeView }}</div>
<div>
<!-- <div v-if="taskInfo && taskInfo.IsShowStudyName">{{ study.StudyName }}</div> -->
<div style="text-overflow: ellipsis;overflow: hidden;">
<span :title="study.CodeView">{{ study.CodeView }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName }}</span>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;">
<span :title="study.BodyPart">{{ study.BodyPart }}</span>
<span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
</div>
@@ -44,7 +48,7 @@
:class="{'file-active': index === activeStudyIndex && i === activeFileIndex}"
class="file-wrapper"
>
<div class="file-image">
<div class="file-image">
<el-image
v-if="k.FileType === 'image/jpeg' || k.FileType === 'image/jpg' || k.FileType === 'image/bmp' || k.FileType === 'image/png'"
style="width: 100%;height: 100%;"
@@ -164,6 +168,9 @@ export default {
text-align: left;
color: #d0d0d0;
padding: 2px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.ps {
@@ -99,9 +99,9 @@
<template slot-scope="scope">
<span>{{
scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: scope.row.Size && scope.row.Size > 0
? `${(scope.row.Size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -324,7 +324,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
handleReset() {
this.searchData = searchDataDefault()
@@ -164,7 +164,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -748,7 +748,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -770,11 +770,12 @@ export default {
},
immediate: true,
},
'rowData.IsEnable': {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
created() {
@@ -766,11 +766,12 @@ export default {
},
immediate: true,
},
'rowData.IsEnable': {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
computed: {
@@ -690,7 +690,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -722,11 +722,12 @@ export default {
},
immediate: true,
},
'rowData.IsEnable': {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
created() {
@@ -843,7 +843,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -865,11 +865,12 @@ export default {
},
immediate: true,
},
'rowData.IsEnable': {
'rowData': {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
deep:true
},
},
created() {
@@ -81,7 +81,7 @@
<template slot-scope="scope">
<span>{{
scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -359,7 +359,6 @@ export default {
status: 'add',
upload: null,
},
DATA: {},
doctorList: [],
}
},
@@ -612,7 +611,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
openFile(isFolder = false) {
this.selectData = {}
@@ -632,12 +631,6 @@ export default {
},
immediate: true,
},
rowData: {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
},
},
created() {
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
@@ -155,6 +155,9 @@ export default {
}
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
isInspect() {
return this.hasPermi([
'trials:trials-panel:trial-summary:trial-document:inspect',
@@ -15,7 +15,7 @@
v-for="(item, index) of siteOptions"
:key="index"
:label="item.TrialSiteCode"
:value="item.SiteId"
:value="item.TrialSiteId"
/>
</el-select>
</el-form-item>
@@ -459,7 +459,7 @@ export default {
},
fileSizeFormatter(size) {
if (!size) return
return (size / Math.pow(1024, 2)).toFixed(3) + 'M'
return (size / Math.pow(1024, 2)).toFixed(3) + 'MB'
},
handleReset() {
this.searchData = searchDataDefault()
@@ -323,7 +323,7 @@
<template slot-scope="scope">
<span>{{
scope.row.Size && scope.row.Size > 0
? `${(scope.row.Size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -434,9 +434,9 @@
scope.row.dicomInfo.fileCount
}}
({{
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(2)
(scope.row.dicomInfo.uploadFileSize / 1024 / 1024).toFixed(3)
}}MB/{{
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(2)
(scope.row.dicomInfo.fileSize / 1024 / 1024).toFixed(3)
}}MB)
</span>
</template>
@@ -92,7 +92,7 @@
<template slot-scope="scope">
<span>{{
scope.row.FileSize && scope.row.FileSize > 0
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.FileSize / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -462,7 +462,7 @@
<template slot-scope="scope">
<span>{{
scope.row.size && scope.row.size > 0
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
@@ -328,7 +328,7 @@
<template slot-scope="scope">
<span>{{
scope.row.Size && scope.row.Size > 0
? `${(scope.row.Size / 1024 / 1024).toFixed(2)}MB`
? `${(scope.row.Size / 1024 / 1024).toFixed(3)}MB`
: ''
}}</span>
</template>
+3 -3
View File
@@ -17,7 +17,7 @@ const name = process.env.NODE_ENV === 'usa' ? 'Imaging Trial Management System'
module.exports = defineConfig({
// lintOnSave: false,
transpileDependencies: false,
publicPath: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? process.env.VUE_APP_BASE_PATH : `${process.env.VUE_FILE_PATH}${process.env.VUE_APP_OSS_PATH}${distDate}/`,
publicPath: process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'prod' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? process.env.VUE_APP_BASE_PATH : `${process.env.VUE_FILE_PATH}${process.env.VUE_APP_OSS_PATH}${distDate}/`,
// publicPath: '/',
outputDir: 'dist',
assetsDir: 'static',
@@ -97,7 +97,7 @@ module.exports = defineConfig({
]
}),
// new BundleAnalyzerPlugin(),
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function() { }
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
: new WebpackAliyunOss({
from: ['./dist/**'],
dist: process.env.VUE_APP_OSS_PATH + distDate,
@@ -184,7 +184,7 @@ module.exports = defineConfig({
// 生成文件的最大体积
maxAssetSize: 3000000000,
// 只给出js的性能提示
assetFilter: function(assetFileName) {
assetFilter: function (assetFileName) {
return assetFileName.endsWith('.js')
}
}