diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue index 6a2afe30..b48dc850 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/ReadPage.vue @@ -438,6 +438,8 @@ @resetAnnotations="resetAnnotations" @setReadingTaskState="setReadingTaskState" @viewCustomAnnotationSeries="viewCustomAnnotationSeries" + @setReadingToolActive="setReadingToolActive" + @setReadingToolPassive="setReadingToolPassive" /> @@ -719,7 +721,8 @@ export default { studyList: [], volumeData: {}, fusionSerieId: {}, - loadingText: null + loadingText: null, + toolNames: ['Length', 'Bidirectional', 'RectangleROI', 'ArrowAnnotate', 'CircleROI', 'Eraser'] // resetAnnotation: false , // 是否初始化标记 (融合时使用) } }, @@ -1160,7 +1163,7 @@ export default { }) toolGroup.addTool(RectangleROITool.toolName, { cachedStats: false, - getTextLines: this.getRectangleROIToolTextLines + getTextLines: this.criterionType === 0 ? this.getCustomRectangleROIToolTextLines : this.getRectangleROIToolTextLines }) toolGroup.addTool(PlanarFreehandROITool.toolName, { allowOpenContours: false, @@ -1685,7 +1688,7 @@ export default { } = cachedVolumeStats || {} const textLines = [] - + if (area) { const areaLine = isEmptyArea ? `Area: Oblique not supported` @@ -1728,11 +1731,23 @@ export default { if (data.label) { textLines.push(data.status ? `${data.label}(${data.status})` : data.label) } - // textLines.push(`Area: ${parseFloat(area).toFixed(this.digitPlaces)} ${areaUnit}`) - // textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`) - // textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`) - // textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`) + return textLines + }, + getCustomRectangleROIToolTextLines(data, targetId) { + const cachedVolumeStats = data.cachedStats[targetId] + const { area, mean, max, stdDev, areaUnit, modalityUnit } = cachedVolumeStats + + if (mean === undefined) { + return + } + + const textLines = [] + textLines.push(`Area: ${this.reRound(area, this.digitPlaces)} ${areaUnit}`) + + textLines.push(`Mean: ${this.reRound(mean, this.digitPlaces)} ${modalityUnit}`) + textLines.push(`Max: ${this.reRound(max, this.digitPlaces)} ${modalityUnit}`) + textLines.push(`Std Dev: ${this.reRound(stdDev, this.digitPlaces)} ${modalityUnit}`) return textLines }, @@ -1751,12 +1766,10 @@ export default { if (length === undefined) { return textLines } - - // spaceBetweenSlices & pixelSpacing & - // magnitude in each direction? Otherwise, this is "px"? + textLines.push( - `L: ${csUtils.roundNumber(length)} ${unit || unit}`, - `S: ${csUtils.roundNumber(width)} ${unit}` + `L: ${parseFloat(length).toFixed(this.digitPlaces)} ${unit || unit}`, + `S: ${parseFloat(width).toFixed(this.digitPlaces)} ${unit}` ) return textLines @@ -1783,31 +1796,48 @@ export default { if (radius) { const radiusLine = isEmptyArea ? `Radius: Oblique not supported` - : `Radius: ${csUtils.roundNumber(radius)} ${radiusUnit}` + : `Radius: ${this.reRound(radius, this.digitPlaces)} ${radiusUnit}` textLines.push(radiusLine) } if (area) { const areaLine = isEmptyArea ? `Area: Oblique not supported` - : `Area: ${csUtils.roundNumber(area)} ${areaUnit}` + : `Area: ${parseFloat(area)} ${areaUnit}` textLines.push(areaLine) } if (mean) { - textLines.push(`Mean: ${csUtils.roundNumber(mean)} ${modalityUnit}`) + textLines.push(`Mean: ${this.reRound(mean, this.digitPlaces)} ${modalityUnit}`) } if (max) { - textLines.push(`Max: ${csUtils.roundNumber(max)} ${modalityUnit}`) + textLines.push(`Max: ${this.reRound(max, this.digitPlaces)} ${modalityUnit}`) } if (stdDev) { - textLines.push(`Std Dev: ${csUtils.roundNumber(stdDev)} ${modalityUnit}`) + textLines.push(`Std Dev: ${this.reRound(stdDev, this.digitPlaces)} ${modalityUnit}`) } return textLines }, + reRound(result, finalPrecision) { + if (result.includes(', ')) { + const numStrs = result.split(', ') + const processed = numStrs.map(str => this.processSingle(str, finalPrecision)) + return processed.join(', ') + } + return this.processSingle(result, finalPrecision) + }, + processSingle(str, precision) { + const num = parseFloat(str) + if (isNaN(num)) return 'NaN' + + // 保留原极小值处理逻辑 + if (Math.abs(num) < 0.0001) return str + const factor = 10 ** precision + return (Math.round(num * factor + 0.0000001) / factor).toFixed(precision) + }, // 激活工具 setToolActive(toolName) { const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}` @@ -1847,6 +1877,37 @@ export default { this.activeTool = toolName } } + if (this.criterionType === 0 && this.readingTaskState < 2) { + this.$refs[`ecrf_${this.taskInfo.VisitTaskId}`][0].resetOperateState() + } + }, + setReadingToolActive(toolName) { + if (this.readingTaskState === 2) return + if (this.activeTool === toolName) return + const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series + if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { + const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + if (this.activeTool) { + toolGroup.setToolPassive(this.activeTool) + } + toolGroup.setToolActive(toolName, { + bindings: [{ mouseButton: MouseBindings.Primary }] + }) + this.activeTool = toolName + } + }, + setReadingToolPassive() { + if (this.readingTaskState === 2) return + if (this.activeTool && this.toolNames.includes(this.activeTool)) { + const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series + if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { + const toolGroupId = `${this.viewportKey}-${this.activeViewportIndex}` + const toolGroup = ToolGroupManager.getToolGroup(toolGroupId) + toolGroup.setToolPassive(this.activeTool) + this.activeTool = '' + } + } }, setMoreToolActive(toolName) { if (this.readingTaskState === 2) return diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionFormItem.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionFormItem.vue index 2e6fcbbb..586c878e 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionFormItem.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionFormItem.vue @@ -232,22 +232,32 @@ - + - 标记 + 测量 + + + + 绑定 i.MeasureData && i.MeasureData.annotationUID === annotation.annotationUID) return i > -1 @@ -354,9 +357,14 @@ export default { async operateImageMarker(obj) { this.operateStateEnum = obj.operateStateEnum this.operateQuestionId = obj.question.Id - if (obj.operateStateEnum === 1) { + this.imageTool = obj.question.ImageTool + this.imageToolAttribute = obj.question.ImageToolAttribute + if (obj.operateStateEnum === 0) { + // 绑定标记 + this.$emit('setReadingToolPassive') + } else if (obj.operateStateEnum === 1) { // 添加标记 - + this.$emit('setReadingToolActive', obj.question.ImageTool) } else if (obj.operateStateEnum === 2) { // 查看标记 const i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id) @@ -366,8 +374,9 @@ export default { } } else if (obj.operateStateEnum === 3) { // 更改标记 - // this.$set(this.questionsMarkStatus, obj.question.Id, 1) + this.$emit('setReadingToolPassive') } else if (obj.operateStateEnum === 4) { + this.$emit('setReadingToolPassive') // 移除标记 this.$set(this.questionForm, obj.question.Id, '') const i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id) @@ -405,14 +414,20 @@ export default { }, async bindAnnotationToQuestion(annotation) { try { - if (!(this.operateStateEnum === 1 || this.operateStateEnum === 3)) return + if (!(this.operateStateEnum === 0 || this.operateStateEnum === 1 || this.operateStateEnum === 3)) return + if (this.operateStateEnum === 1 && annotation.markTool !== this.imageTool) return if (!this.operateQuestionId) return - if (this.operateStateEnum === 3) { + if (this.operateStateEnum === 0 || this.operateStateEnum === 3) { if (!annotation.data.label) { this.$alert('该标记不能与问题绑定!') return } - const confirm = await this.$confirm('是否确认更改?', { + if (annotation.markTool !== this.imageTool) { + this.$alert('该标记不能与问题绑定!') + return + } + let msg = this.operateStateEnum === 0 ? '是否确认绑定?' : '是否确认更改?' + const confirm = await this.$confirm(msg, { type: 'warning', distinguishCancelAndClose: true }) @@ -449,7 +464,6 @@ export default { } }, updateAnnotationToQuestion(annotation) { - console.log('updateAnnotationToQuestion', annotation) const i = this.questionMarkInfoList.findIndex(i => i.MeasureData && i.MeasureData.annotationUID === annotation.annotationUID) if (i === -1) return this.questionMarkInfoList[i].measureData = annotation @@ -464,13 +478,25 @@ export default { length = length ? parseFloat(length).toFixed(this.digitPlaces) : length this.$set(this.questionForm, questionId, length) } else if (annotation.metadata.toolName === 'Bidirectional') { - // let length = annotation.data.cachedStats[`imageId:${referencedImageId}`].length - // length = length ? parseFloat(length).toFixed(this.digitPlaces) : length - let short = annotation.data.cachedStats[`imageId:${referencedImageId}`].width - short = short ? parseFloat(short).toFixed(this.digitPlaces) : short - this.$set(this.questionForm, questionId, short) + if (this.imageToolAttribute === 'length') { + let length = annotation.data.cachedStats[`imageId:${referencedImageId}`].length + length = length ? parseFloat(length).toFixed(this.digitPlaces) : length + this.$set(this.questionForm, questionId, length) + } else if (this.imageToolAttribute === 'width') { + let short = annotation.data.cachedStats[`imageId:${referencedImageId}`].width + short = short ? parseFloat(short).toFixed(this.digitPlaces) : short + this.$set(this.questionForm, questionId, short) + } } }, + resetOperateState() { + console.log('resetOperateState') + this.operateStateEnum = null + this.operateQuestionId = '' + this.operateRowId = '' + this.imageTool = '' + this.imageToolAttribute = '' + }, async resetForm() { const confirm = await this.$confirm( this.$t('trials:dicomReading:message:confirmReset1'), diff --git a/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionTableFormItem.vue b/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionTableFormItem.vue index 547c1f0f..114c3d39 100644 --- a/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionTableFormItem.vue +++ b/src/views/trials/trials-panel/reading/dicoms3D/components/customize/QuestionTableFormItem.vue @@ -460,6 +460,7 @@ export default { }, formItemNumberChange(v, question) { this.$emit('formItemTableNumberChange', v, question) + this.$emit('setFormItemData', { key: question.Id, val: v, question: question }) // this.$emit('formItemTableNumberChange', v, question) }, resetChild(obj) { diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/QuestionTableFormItem.vue b/src/views/trials/trials-panel/setting/reading-unit/components/QuestionTableFormItem.vue index 9fea8c37..3399d21f 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/QuestionTableFormItem.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/QuestionTableFormItem.vue @@ -353,7 +353,9 @@ export default { } }, formItemNumberChange(v, question) { - this.$emit('formItemTableNumberChange', v, question) + // this.$emit('formItemTableNumberChange', v, question) + this.$emit('formItemTableNumberChange') + this.$emit('setFormItemData', { key: question.Id, val: v, question: question }) }, resetChild(obj) { obj.forEach(i => { diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsForm.vue b/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsForm.vue index a88e38b2..64a17655 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsForm.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsForm.vue @@ -729,17 +729,62 @@ {{ item.label }} + + + + + {{ $t(tool.i18nKey) }} + + + + + + + + {{ i }} + + + 0) { @@ -1477,8 +1539,20 @@ export default { form.ImageMarkEnum = 0 } }, + imageMarkEnumChange(val) { + if (val === 0) { + this.form.ImageTool = '' + this.form.ImageToolAttribute = '' + this.imageToolAttributes = [] + } + }, + imageToolChange(v) { + let i = this.readingTools.findIndex(tool=>tool.toolName === v) + if (i > -1) { + this.imageToolAttributes = this.readingTools[i].props + } + }, parentQuestionChange(val, form) { - console.log(val) this.isParentExistGroup = false if (val) { var index = this.parentOptions.findIndex(item => { @@ -1571,6 +1645,9 @@ export default { form.ClassifyType = null form.ClassifyShowType = null form.ImageMarkEnum = 0 + form.ImageTool = '' + form.ImageToolAttribute = '' + this.imageToolAttributes = [] }, getLesionType() { return new Promise((resolve, reject) => { diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsList.vue b/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsList.vue index 2d5a5e0b..42f51c49 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsList.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/QuestionsList.vue @@ -210,12 +210,14 @@ append-to-body custom-class="base-dialog-wrapper" > - - + - - @@ -77,6 +79,12 @@ export default { isAdditionalAssessment: { type: Boolean, default: false + }, + readingTools: { + type: Array, + default() { + return [] + } } }, data() { @@ -99,7 +107,8 @@ export default { readingInfo: {}, isConfirm: true, configBaseDataVisible: false, - additionalAssessmentOptionList: null + additionalAssessmentOptionList: null, + readingVersionEnum: 0 } }, mounted() { @@ -118,6 +127,7 @@ export default { } getTrialReadingCriterionInfo({ trialId, TrialReadingCriterionId: this.trialReadingCriterionId }).then(res => { this.loading = false + this.readingVersionEnum = res.OtherInfo.ReadingVersionEnum this.readingInfo = res.Result for (const k in this.form) { if (res.Result.hasOwnProperty(k)) { @@ -126,7 +136,6 @@ export default { } this.isConfirm = res.Result.IsSign this.isSystemCriterion = res.Result.IsSystemCriterion - console.log(this.isSystemCriterion) }).catch(() => { this.loading = false }) @@ -137,7 +146,6 @@ export default { // 配置信息保存 handleSave(isPrompt = true) { return new Promise((resolve, reject) => { - console.log(this.form) this.$refs['readingCriterionsForm'].validate((valid) => { if (!valid) { resolve(false) diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/ReadingRules.vue b/src/views/trials/trials-panel/setting/reading-unit/components/ReadingRules.vue index d0d8853c..2572ac82 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/ReadingRules.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/ReadingRules.vue @@ -917,6 +917,8 @@ export default { this.$emit('setGlobalReading', res.Result.IsGlobalReading) this.$emit('setOncologyReading', res.Result.IsOncologyReading) this.$emit('setDigitPlaces', res.Result.DigitPlaces) + this.$emit('setReadingTools', res.Result.ReadingToolList) + if (res.Result.ReadingType === 1) { this.$emit('setArbitrationReading', false) } @@ -957,6 +959,7 @@ export default { this.$emit('setGlobalReading', this.form.IsGlobalReading) this.$emit('setOncologyReading', this.form.IsOncologyReading) this.$emit('setDigitPlaces', this.form.DigitPlaces) + this.$emit('setReadingTools', this.form.ReadingToolList) if (this.form.ReadingType === 1) { this.$emit('setArbitrationReading', false) } diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/TableQsForm.vue b/src/views/trials/trials-panel/setting/reading-unit/components/TableQsForm.vue index 9f2e4f2f..d8ca1752 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/TableQsForm.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/TableQsForm.vue @@ -1199,6 +1199,12 @@ export default { } } }, + classifyQuestionChange (v){ + let obj = this.selectQuestions.find(i=>i.Id === v) + let arr = obj && obj.TypeValue ? obj.TypeValue.split('|') : [] + arr = arr.length > 0 ? arr.map(i=>i.trim()) : [] + this.classifyQuestionOptions = arr + }, getBasicConfigSelect() { getCriterionDictionaryList({ CriterionId: this.criterionId, diff --git a/src/views/trials/trials-panel/setting/reading-unit/index.vue b/src/views/trials/trials-panel/setting/reading-unit/index.vue index b422f1c2..a1cd1268 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/index.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/index.vue @@ -46,6 +46,7 @@ @setGlobalReading="setGlobalReading" @setOncologyReading="setOncologyReading" @setDigitPlaces="setDigitPlaces" + @setReadingTools="setReadingTools" /> @@ -57,6 +58,7 @@ :ref="`readingCriterions${item.TrialReadingCriterionId}`" :trial-reading-criterion-id="TrialReadingCriterionId" :digit-places="digitPlaces" + :readingTools="readingTools" :is-additional-assessment="isAdditionalAssessment" @reloadArbitrationRules="reloadArbitrationRules" /> @@ -174,7 +176,7 @@ import GlobalReading from "./components/GlobalReading"; import OncologyForm from "./components/OncologyForm"; import SignForm from "@/views/trials/components/newSignForm"; import const_ from "@/const/sign-code"; - +import { getCustomizeStandardsTools } from '@/views/trials/trials-panel/reading/dicoms3D/components/toolConfig' export default { name: "ReadingUnit", components: { @@ -208,6 +210,7 @@ export default { isGlobalReading: false, digitPlaces: 0, isAdditionalAssessment: false, + readingTools: [] }; }, watch: { @@ -295,6 +298,9 @@ export default { setDigitPlaces(digitPlaces) { this.digitPlaces = digitPlaces; }, + setReadingTools(readingTools) { + this.readingTools = getCustomizeStandardsTools(readingTools) + }, setIsClinicalReading(isClinicalReading) { this.isClinicalReading = isClinicalReading; },