自定义标准阅片交互更改

main
caiyiling 2025-06-06 17:25:23 +08:00
parent 8d5dfd0258
commit f98ea18205
6 changed files with 321 additions and 246 deletions

View File

@ -596,6 +596,8 @@ const {
// RectangleROITool,
PlanarFreehandROITool,
CircleROITool,
AngleTool,
CobbAngleTool,
EraserTool,
MIPJumpToClickTool,
VolumeRotateTool,
@ -1136,6 +1138,8 @@ export default {
cornerstoneTools.addTool(BidirectionalTool)
cornerstoneTools.addTool(ScaleOverlayTool)
cornerstoneTools.addTool(CircleROITool)
cornerstoneTools.addTool(AngleTool)
cornerstoneTools.addTool(CobbAngleTool)
cornerstoneTools.addTool(MIPJumpToClickTool)
cornerstoneTools.addTool(VolumeRotateTool)
@ -1183,6 +1187,12 @@ export default {
toolGroup.addTool(CircleROITool.toolName, {
getTextLines: this.getCircleROIToolTextLines
})
toolGroup.addTool(AngleTool.toolName, {
getTextLines: this.getAngleToolTextLines
})
toolGroup.addTool(CobbAngleTool.toolName, {
getTextLines: this.getCobbAngleToolTextLines
})
if (toolGroupId === 'viewport-fusion-3') {
toolGroup.addTool(VolumeRotateTool.toolName)
toolGroup.setToolActive(VolumeRotateTool.toolName, {
@ -1229,6 +1239,8 @@ export default {
toolGroup.setToolPassive(LengthTool.toolName)
toolGroup.setToolPassive(BidirectionalTool.toolName)
toolGroup.setToolPassive(CircleROITool.toolName)
toolGroup.setToolPassive(AngleTool.toolName)
toolGroup.setToolPassive(CobbAngleTool.toolName)
} else {
toolGroup.setToolEnabled(ArrowAnnotateTool.toolName)
toolGroup.setToolEnabled(RectangleROITool.toolName)
@ -1236,6 +1248,8 @@ export default {
toolGroup.setToolEnabled(LengthTool.toolName)
toolGroup.setToolEnabled(BidirectionalTool.toolName)
toolGroup.setToolEnabled(CircleROITool.toolName)
toolGroup.setToolEnabled(AngleTool.toolName)
toolGroup.setToolEnabled(CobbAngleTool.toolName)
}
toolGroup.setToolPassive(EraserTool.toolName)
})
@ -1666,7 +1680,6 @@ export default {
}
const textLines = []
if (data.label) {
// textLines.push(data.label)
textLines.push(data.status ? `${data.label}(${data.status})` : data.label)
}
textLines.push(`${parseFloat(length).toFixed(this.digitPlaces)} ${unit}`)
@ -1688,7 +1701,9 @@ export default {
} = cachedVolumeStats || {}
const textLines = []
if (data.label) {
textLines.push(data.label)
}
if (area) {
const areaLine = isEmptyArea
? `Area: Oblique not supported`
@ -1743,6 +1758,9 @@ export default {
}
const textLines = []
if (data.label) {
textLines.push(data.label)
}
textLines.push(`Area: ${this.reRound(area, this.digitPlaces)} ${areaUnit}`)
textLines.push(`Mean: ${this.reRound(mean, this.digitPlaces)} ${modalityUnit}`)
@ -1756,11 +1774,8 @@ export default {
const { length, width, unit } = cachedStats[targetId]
const textLines = []
// if (label) {
// textLines.push(label);
// }
if (label) {
// textLines.push(label)
textLines.push(data.status ? `${label}(${data.status})` : label)
}
if (length === undefined) {
@ -1790,7 +1805,7 @@ export default {
const textLines = []
if (data.label) {
// textLines.push(data.label)
textLines.push(data.status ? `${data.label}(${data.status})` : data.label)
textLines.push(data.label)
}
if (radius) {
@ -1821,8 +1836,40 @@ export default {
return textLines
},
getAngleToolTextLines(data, targetId) {
const cachedVolumeStats = data.cachedStats[targetId]
const { angle } = cachedVolumeStats
if (angle === undefined) {
return
}
if (isNaN(angle)) {
return [`${angle}`]
}
const textLines = []
if (label) {
textLines.push(label)
}
textLines.push(`${angle.toFixed(this.digitPlaces)} ${String.fromCharCode(176)}`)
return textLines
},
getCobbAngleToolTextLines(data, targetId) {
const cachedVolumeStats = data.cachedStats[targetId]
const { angle } = cachedVolumeStats
if (angle === undefined) {
return
}
const textLines = []
if (label) {
textLines.push(label)
}
textLines.push(`${angle.toFixed(this.digitPlaces)} ${String.fromCharCode(176)}`)
return textLines
},
reRound(result, finalPrecision) {
if (result.includes(', ')) {
if (typeof result === 'string' && result.includes(', ')) {
const numStrs = result.split(', ')
const processed = numStrs.map(str => this.processSingle(str, finalPrecision))
return processed.join(', ')

View File

@ -232,9 +232,9 @@
<el-input
type="number"
@change="(val) => { formItemNumberChange(val, question) }"
@blur="!questionsMarkStatus[question.Id] ? handleBlur(questionForm[question.Id], questionForm, question.Id) : ()=>{}"
@blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? ()=>{} : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question) "
v-model="questionForm[question.Id]"
:disabled="(questionsMarkStatus[question.Id] && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1"
:disabled="(questionsMarkStatus[question.Id].isMarked && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1"
style="width: 150px;"
>
<template v-if="question.Unit !== 0" slot="append">
@ -243,7 +243,7 @@
</el-input>
<!-- 测量 -->
<el-button
v-if="readingTaskState < 2 && !questionsMarkStatus[question.Id]"
v-if="readingTaskState < 2 && (!questionsMarkStatus[question.Id].isMarked)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 1, question})"
@ -252,7 +252,7 @@
</el-button>
<!-- 绑定 -->
<el-button
v-if="readingTaskState < 2 && !questionsMarkStatus[question.Id]"
v-if="readingTaskState < 2 && (!questionsMarkStatus[question.Id].isMarked)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 0, question})"
@ -261,7 +261,7 @@
</el-button>
<!-- 查看 -->
<el-button
v-if="questionsMarkStatus[question.Id]"
v-if="questionsMarkStatus[question.Id].isMarked"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 2, question})"
@ -270,7 +270,7 @@
</el-button>
<!-- 更改 -->
<el-button
v-if="readingTaskState < 2 && questionsMarkStatus[question.Id]"
v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id].isMarked)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 3, question})"
@ -279,7 +279,7 @@
</el-button>
<!-- 移除 -->
<el-button
v-if="readingTaskState < 2 && questionsMarkStatus[question.Id]"
v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id].isMarked)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 4, question})"
@ -288,12 +288,12 @@
</el-button>
<!-- 保存 -->
<el-button
v-if="readingTaskState < 2 && questionsMarkStatus[question.Id]"
v-if="readingTaskState < 2 && !questionsMarkStatus[question.Id].isSaved"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 5, question})"
>
<el-tooltip v-if="questionsMarkStatus[question.Id] === 1" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<el-tooltip v-if="!questionsMarkStatus[question.Id].isSaved" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<i class="el-icon-warning" style="color:red" />
</el-tooltip>
保存
@ -601,6 +601,10 @@ export default {
handleBlur(value, a, b) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
},
handleMarkedQsBlur(value, a, b, question) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
this.$emit('operateImageMarker', {operateStateEnum: 6, question})
},
deleteTableCol(row, index) {
this.$confirm(this.$t('trials:uploadNonDicoms:message:msg1')).then(() => {
const loading = this.$loading({ fullscreen: true })

View File

@ -123,7 +123,7 @@ export default {
operateRowId: '',
imageTool: '',
imageToolAttribute: '',
questionsMarkStatus: {}, // 12
questionsMarkStatus: {},
digitPlaces: 2
}
},
@ -169,8 +169,8 @@ export default {
this.questions = res.Result.SinglePage
this.questionsMarkStatus = {}
this.questionMarkInfoList = res.OtherInfo.QuestionMarkInfoList.map(i => {
if (i.QuestionId && i.MeasureData) {
this.$set(this.questionsMarkStatus, i.QuestionId, 2)
if (i.QuestionId) {
this.$set(this.questionsMarkStatus, i.QuestionId, {isMarked: i.MeasureData !== '', isSaved: true})
}
if (typeof i.MeasureData === 'string' && i.MeasureData) {
i.MeasureData = JSON.parse(i.MeasureData)
@ -381,9 +381,12 @@ export default {
this.$set(this.questionForm, obj.question.Id, '')
const i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id)
if (i > -1) {
this.questionMarkInfoList.splice(i, 1)
this.questionMarkInfoList[i].MeasureData = ''
this.questionMarkInfoList[i].StudyId = ''
this.questionMarkInfoList[i].SeriesId = ''
this.questionMarkInfoList[i].InstanceId = ''
}
this.$set(this.questionsMarkStatus, obj.question.Id, 0)
this.$set(this.questionsMarkStatus, obj.question.Id, {isMarked: false, isSaved: false})
} else if (obj.operateStateEnum === 5) {
//
this.loading = true
@ -404,12 +407,15 @@ export default {
}
await saveTaskQuestion(-10, params)
this.$set(this.questionsMarkStatus, obj.question.Id, 2)
this.$set(this.questionsMarkStatus, obj.question.Id, {isMarked: this.questionMarkInfoList[i].MeasureData ? true : false, isSaved: true})
this.loading = false
} catch (e) {
console.log(e)
this.loading = false
}
} else if (obj.operateStateEnum === 6) {
//
this.$set(this.questionsMarkStatus, obj.question.Id, {isMarked: false, isSaved: false})
}
},
async bindAnnotationToQuestion(annotation) {
@ -458,7 +464,7 @@ export default {
this.questionMarkInfoList[i].MeasureData = annotation
}
this.setAnswerToQuestion(annotation, this.operateQuestionId)
this.$set(this.questionsMarkStatus, this.operateQuestionId, 1)
this.$set(this.questionsMarkStatus, this.operateQuestionId, {isMarked: true, isSaved: false})
} catch (e) {
console.log(e)
}
@ -468,7 +474,7 @@ export default {
if (i === -1) return
this.questionMarkInfoList[i].measureData = annotation
this.setAnswerToQuestion(annotation, this.questionMarkInfoList[i].QuestionId)
this.$set(this.questionsMarkStatus, this.questionMarkInfoList[i].QuestionId, 1)
this.$set(this.questionsMarkStatus, this.questionMarkInfoList[i].QuestionId, {isMarked: true, isSaved: false})
},
setAnswerToQuestion(annotation, questionId) {
if (!questionId || !annotation) return

View File

@ -1,233 +1,233 @@
<template>
<div class="criterion-form-item">
<el-form-item
v-if="(question.ShowQuestion===1 && !!~question.ParentTriggerValueList.indexOf(questionForm[question.ParentId])) || question.ShowQuestion===0"
:label="`${question.QuestionName}`"
:prop="question.Id"
:rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && !!~question.RelevanceValueList.indexOf(questionForm[question.RelevanceId]))) && question.Type!=='group' && question.Type!=='summary',
message: $t('common:ruleMessage:select'), trigger: ['blur', 'change']},
]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
v-if="(question.ShowQuestion===1 && !!~question.ParentTriggerValueList.indexOf(questionForm[question.ParentId])) || question.ShowQuestion===0"
:label="`${question.QuestionName}`"
:prop="question.Id"
:rules="[
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && !!~question.RelevanceValueList.indexOf(questionForm[question.RelevanceId]))) && question.Type!=='group' && question.Type!=='summary',
message: $t('common:ruleMessage:select'), trigger: ['blur', 'change']},
]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
>
<!-- 输入框 -->
<el-input
v-if="question.Type==='input'"
v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
/>
<!-- 多行文本输入框 -->
<el-input
v-if="question.Type==='textarea'"
v-model="questionForm[question.Id]"
type="textarea"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<!-- 下拉框 -->
<el-select
v-if="question.Type==='select'"
v-model="questionForm[question.Id]"
clearable
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) || (question.IsCopy && type === 'edit' && !IsBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemChange(val, question)})"
>
<!-- 输入框 -->
<el-input
v-if="question.Type==='input'"
v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
/>
<!-- 多行文本输入框 -->
<el-input
v-if="question.Type==='textarea'"
v-model="questionForm[question.Id]"
type="textarea"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
:autosize="{ minRows: 2, maxRows: 4}"
/>
<!-- 下拉框 -->
<el-select
v-if="question.Type==='select'"
v-model="questionForm[question.Id]"
clearable
:disabled="(question.TableQuestionType === 2 || question.QuestionGenre === 2) || (question.IsCopy && type === 'edit' && !IsBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.TableQuestionType === 1">
<el-option
v-for="item in organList"
:key="item.Id"
:label="item[question.DataTableColumn]"
:value="item[question.DataTableColumn]"
/>
</template>
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
<el-option
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
<el-option
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<template v-else>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
/>
</template>
</el-select>
<!-- 单选 -->
<el-radio-group
v-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemChange(val, question)})"
>
<el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }}
</el-radio>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-if="question.Type==='checkbox'"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
v-model="questionForm[question.Id]"
>
<el-checkbox
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }}
</el-checkbox>
</el-checkbox-group>
<!-- 自动分类 -->
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<template v-if="question.TableQuestionType === 1">
<el-option
v-for="item in organList"
:key="item.Id"
:label="item[question.DataTableColumn]"
:value="item[question.DataTableColumn]"
/>
</template>
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
<el-option
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
<el-option
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template>
<template v-else>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
:label="val"
:value="val"
/>
</el-select>
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
v-for="item of question.TypeValue.split('|')"
:key="item.trim()"
:label="item.trim()"
>
{{ item.trim() }}
</el-radio>
</el-radio-group>
<!-- 自动计算 -->
<!-- :precision="2" :step="0.1" :max="10" -->
<el-input
v-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
oninput="value=value.replace(/^\D*(\d*(?:.\d{0,2})?).*$/g, '$1')"
disabled
/>
<!-- 自增 -->
<el-input
v-if="question.Type==='increment'"
v-model="questionForm[question.Id]"
disabled
/>
<!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" -->
<el-input
type="number"
v-if="question.Type === 'number' && question.DataSource !== 1"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemNumberChange(val, question)})"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
v-model="questionForm[question.Id]"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
</el-input>
<el-input
type="number"
v-if="question.Type === 'number' && question.DataSource === 1"
:disabled="question.DataSource === 1"
@blur="handleCalculationBlur(calculationValue)"
v-model="calculationValue"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
</el-input>
<!-- 上传图像 -->
<el-upload
v-if="question.Type==='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: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}"
>
<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>
</template>
<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>
<el-dialog
v-if="question.Type==='upload'"
append-to-body
:visible.sync="imgVisible"
width="600px"
</el-select>
<!-- 单选 -->
<el-radio-group
v-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemChange(val, question)})"
>
<el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
<el-image :src="imageUrl" width="100%">
<div slot="placeholder" class="image-slot">
{{$t('trials:readingUnit:qsList:message:loading')}}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
</el-form-item>
{{ val }}
</el-radio>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-if="question.Type==='checkbox'"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
v-model="questionForm[question.Id]"
>
<el-checkbox
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }}
</el-checkbox>
</el-checkbox-group>
<!-- 自动分类 -->
<el-input
v-if="question.Type === 'class' && question.ClassifyShowType === 1"
v-model="questionForm[question.Id]"
/>
<el-select
v-if="question.Type === 'class' && question.ClassifyShowType === 2"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val.trim()"
:value="val.trim()"
/>
</el-select>
<el-radio-group
v-if="question.Type === 'class' && question.ClassifyShowType === 3"
v-model="questionForm[question.Id]"
:disabled="!question.ClassifyEditType"
@change="(val) => { formItemChange(val, question) }"
>
<el-radio
v-for="item of question.TypeValue.split('|')"
:key="item.trim()"
:label="item.trim()"
>
{{ item.trim() }}
</el-radio>
</el-radio-group>
<!-- 自动计算 -->
<!-- :precision="2" :step="0.1" :max="10" -->
<el-input
v-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
oninput="value=value.replace(/^\D*(\d*(?:.\d{0,2})?).*$/g, '$1')"
disabled
/>
<!-- 自增 -->
<el-input
v-if="question.Type==='increment'"
v-model="questionForm[question.Id]"
disabled
/>
<!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" -->
<el-input
type="number"
v-if="question.Type === 'number' && question.DataSource !== 1"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemNumberChange(val, question)})"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
v-model="questionForm[question.Id]"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
</el-input>
<el-input
type="number"
v-if="question.Type === 'number' && question.DataSource === 1"
:disabled="question.DataSource === 1"
@blur="handleCalculationBlur(calculationValue)"
v-model="calculationValue"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
</el-input>
<!-- 上传图像 -->
<el-upload
v-if="question.Type==='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: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount}"
>
<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>
<el-dialog
v-if="question.Type==='upload'"
append-to-body
:visible.sync="imgVisible"
width="600px"
>
<el-image :src="imageUrl" width="100%">
<div slot="placeholder" class="image-slot">
{{$t('trials:readingUnit:qsList:message:loading')}}<span class="dot">...</span>
</div>
</el-image>
</el-dialog>
</el-form-item>
</div>
</template>
<script>

View File

@ -274,6 +274,24 @@ const config = {
'i18nKey': 'trials:reading:button:Circle',
'isDisabled': false,
'disabledReason': ''
},
{
'name': '角度工具',
'icon': 'angle',
'toolName': 'Angle',
'props': ['angle'],
'i18nKey': 'trials:reading:button:Angle',
'isDisabled': false,
'disabledReason': ''
},
{
'name': '角度工具',
'icon': 'cobb',
'toolName': 'CobbAngle',
'props': ['angle'],
'i18nKey': 'trials:reading:button:CobbAngle',
'isDisabled': false,
'disabledReason': ''
}
]
}

View File

@ -1095,7 +1095,7 @@ export default {
return textLines
},
reRound(result, finalPrecision) {
if (result.includes(', ')) {
if (typeof result === 'string' && result.includes(', ')) {
const numStrs = result.split(', ')
const processed = numStrs.map(str => this.processSingle(str, finalPrecision))
return processed.join(', ')