dicom阅片更改
parent
e3ad114207
commit
42711dadb5
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,318 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
</h4>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-form-item
|
||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
||||
>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='textarea'"
|
||||
v-model="questionForm[question.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
maxlength="500"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-else-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode)"
|
||||
clearable
|
||||
@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="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<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-else-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-radio
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
<template v-else-if="question.TypeValue">
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-else-if="question.Type==='checkbox'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<!-- 数值 -->
|
||||
<template v-else-if="question.Type==='number'">
|
||||
<el-input-number
|
||||
v-if="question.ValueType === 0"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="0"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
</template>
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
<!-- 上传图像 -->
|
||||
<el-upload
|
||||
v-else-if="question.Type==='upload'"
|
||||
action
|
||||
:accept="accept"
|
||||
:limit="question.ImageCount"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:http-request="uploadScreenshot"
|
||||
list-type="picture-card"
|
||||
:on-remove="handleRemove"
|
||||
:file-list="fileList"
|
||||
:class="{disabled:fileList.length >= question.ImageCount}"
|
||||
:disabled="readingTaskState >= 2"
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
alt=""
|
||||
>
|
||||
<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>
|
||||
</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">
|
||||
加载中<span class="dot">...</span>
|
||||
</div>
|
||||
</el-image>
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<question-form-item
|
||||
v-for="(item) in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
:visitTaskId="visitTaskId"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import { uploadReadingAnswerImage } from '@/api/trials'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'QuestionFormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: '',
|
||||
urls: [],
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
// console.log(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
} else {
|
||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
::v-deep .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start;
|
||||
}
|
||||
::v-deep .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
::v-deep .el-input-group__append, .el-input-group__prepend{
|
||||
padding: 0 10px;
|
||||
}
|
||||
::v-deep .el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
::v-deep .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,352 @@
|
|||
<template>
|
||||
<div class="table-question-form">
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<h3 v-if="questionForm.LesionName" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ questionForm.LesionName }}
|
||||
</h3>
|
||||
<!-- 关闭 -->
|
||||
<div>
|
||||
<i class="el-icon-circle-close" style="font-size: 25px;cursor: pointer;" @click="close" />
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item
|
||||
:label="$t('trials:reading:title:lesionType')"
|
||||
prop="LesionType"
|
||||
:rules="[
|
||||
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['blur']},
|
||||
]"
|
||||
>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-model="questionForm.LesionType"
|
||||
filterable
|
||||
:disabled="!isCurrentTask || readingTaskState>=2 || !isBaseLineTask"
|
||||
@change="((val)=>{lesionTypeChange(val)})"
|
||||
>
|
||||
|
||||
<el-option
|
||||
v-for="item of $d.LesionType"
|
||||
v-show="!(isBaseLineTask && item.value === 2)"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-for="qs in questions"
|
||||
v-show="qs.ShowQuestion!==2"
|
||||
:key="qs.Id"
|
||||
:label="`${qs.QuestionName}`"
|
||||
:prop="qs.Id"
|
||||
:rules="[
|
||||
{ required: (qs.IsRequired === 0 || (qs.IsRequired ===1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10)) && qs.Type!=='group' && qs.Type!=='summary',
|
||||
message:['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
|
||||
]"
|
||||
>
|
||||
<!-- 输入框 -->
|
||||
<template v-if="qs.Type==='input' || qs.Type==='number'">
|
||||
<el-input
|
||||
v-if="qs.Type==='input' || qs.Type==='number'"
|
||||
v-model="questionForm[qs.Id]"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName))"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
>
|
||||
<template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(qs.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-if="qs.Type==='textarea'"
|
||||
v-model="questionForm[qs.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-if="qs.Type==='select'"
|
||||
v-model="questionForm[qs.Id]"
|
||||
filterable
|
||||
:placeholder="qs.QuestionMark === 8 ? $t('common:placeholder:selectorsearch') : qs.QuestionMark === 2 ? '' : $t('common:placeholder:select')"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False'|| !!answer.SplitOrMergeLesionName)) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
>
|
||||
<template v-if="qs.QuestionMark === 8" #prefix>
|
||||
<span style="padding-left: 5px;">
|
||||
<i class="el-icon-search" />
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="qs.TableQuestionType === 1">
|
||||
<el-option
|
||||
v-for="item in organList"
|
||||
:key="item.Id"
|
||||
:label="item[qs.DataTableColumn]"
|
||||
:value="item[qs.DataTableColumn]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && isBaseLineTask">
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
v-show="(lesionType === 0 && item.value ===0) || (lesionType === 1 && (item.value ===0))"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask">
|
||||
<el-option-group
|
||||
:label="!isNaN(parseFloat(answer.LastTaskState)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(qs.DictionaryCode,parseFloat(answer.LastTaskState))}` : ''"
|
||||
>
|
||||
<!-- 首次分裂的病灶只能选择存在 -->
|
||||
<template v-if="answer.IsFristAdd=== 'True' && answer.SplitOrMergeType === '0'">
|
||||
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
v-show="item.value === 0"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<!-- 首次添加的新病灶不能为无法评估和消失 -->
|
||||
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
v-show="item.value === 0 || item.value === 1"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="item of filterState($d[qs.DictionaryCode])"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-option-group>
|
||||
</template>
|
||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in qs.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-if="qs.Type==='radio'"
|
||||
v-model="questionForm[qs.id]"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
||||
>
|
||||
<el-radio
|
||||
v-for="val in qs.options.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'TableQuestionFormItem',
|
||||
props: {
|
||||
tableInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
answer: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
organs: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
isBaseLineTask: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isCurrentTask: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
if (v.MeasureData) {
|
||||
const {markTool} = v.MeasureData
|
||||
if (markTool === 'Bidirectional') {
|
||||
this.getOrganList(1)
|
||||
} else if (markTool === 'Length') {
|
||||
this.getOrganList(0)
|
||||
} else {
|
||||
this.getOrganList()
|
||||
}
|
||||
} else {
|
||||
this.getOrganList()
|
||||
}
|
||||
this.isCurrentTaskAdd = v.IsCurrentTaskAdd
|
||||
}
|
||||
},
|
||||
tableInfo: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
if (v) {
|
||||
this.lesionType = v.LesionType
|
||||
this.questions = v.TableQuestions.Questions
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
data(){
|
||||
return{
|
||||
isCurrentTaskAdd: null,
|
||||
lesionType: null,
|
||||
questions: [],
|
||||
organList: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
lesionTypeChange(v) {
|
||||
this.$emit('lesionTypeChange', {tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, newLesionType: v})
|
||||
},
|
||||
formItemChange(v, qs) {
|
||||
let updateArr = []
|
||||
if (qs.QuestionMark === 8 && qs.RelationQuestions.length > 0) {
|
||||
// 当选择部位时,联动器官、位置、是否淋巴结问题答案
|
||||
let index = this.organList.findIndex(item => item[qs.DataTableColumn] === v)
|
||||
if (index > -1) {
|
||||
let selected = this.organList[index]
|
||||
qs.RelationQuestions.map(q => {
|
||||
let val = selected[q.DataTableColumn]
|
||||
updateArr.push({questionId: q.Id, val: val, questionMark: q.QuestionMark})
|
||||
})
|
||||
updateArr.push({questionId: 'OrganInfoId', val: selected.OrganInfoId})
|
||||
updateArr.push({questionId: 'IsCanEditPosition', val: selected.IsCanEditPosition})
|
||||
} else {
|
||||
question.RelationQuestions.map(q => {
|
||||
updateArr.push({questionId: q.Id, val: '', questionMark: q.QuestionMark})
|
||||
})
|
||||
}
|
||||
}
|
||||
this.$emit('update', {tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, questionMark: qs.QuestionMark, questionId: qs.Id, val: v, updateArr})
|
||||
},
|
||||
getOrganList(isLymphNodes = null) {
|
||||
let idx = this.organs.findIndex(i => i.LesionType === this.questionForm.LesionType)
|
||||
if (idx > -1) {
|
||||
let arr = this.organs[idx].OrganList
|
||||
|
||||
if (!isNaN(parseInt(isLymphNodes))) {
|
||||
this.organList = arr.filter((item) => item.IsLymphNodes === parseInt(isLymphNodes))
|
||||
} else {
|
||||
this.organList = arr
|
||||
}
|
||||
}
|
||||
},
|
||||
filterState(arr) {
|
||||
if (!this.isBaseLineTask) {
|
||||
const isLymphLesion = this.questionForm.IsLymphNodes
|
||||
const lesionLength = this.questionForm.LesionLength
|
||||
const lesionShort = this.questionForm.LesionShort
|
||||
const bLesionL = !isNaN(parseFloat(this.questionForm.BaseLineMajorAxis)) ? parseFloat(this.questionForm.BaseLineMajorAxis) : 0
|
||||
const bLesionS = !isNaN(parseFloat(this.questionForm.BaseLineShortAxis)) ? parseFloat(this.questionForm.BaseLineShortAxis) : 0
|
||||
if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort < bLesionS) {
|
||||
arr = arr.filter(i => i.value !== 1)
|
||||
} else if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort >= 10 && lesionShort > bLesionS) {
|
||||
arr = arr.filter(i => i.value === 0 || i.value === 1)
|
||||
} else if (this.lesionType === 1 && isLymphLesion === 0 && this.questionForm.MeasureData && (this.questionForm.MeasureData.markTool === 'Length' || this.questionForm.MeasureData.markTool === 'Bidirectional') && lesionLength < bLesionL) {
|
||||
arr = arr.filter(i => i.value !== 1)
|
||||
}
|
||||
return arr
|
||||
} else {
|
||||
return arr
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$emit('close', {tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table-question-form{
|
||||
::v-deep .el-form-item__label{
|
||||
color: #c3c3c3;
|
||||
}
|
||||
::v-deep .el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
::v-deep .el-form-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
::v-deep .el-form-item__content{
|
||||
flex: 1;
|
||||
}
|
||||
::v-deep .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
::v-deep .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
::v-deep .el-button--mini, .el-button--mini.is-round {
|
||||
padding: 7px 10px;
|
||||
}
|
||||
.el-form-item__content
|
||||
.el-select{
|
||||
width: 100%;
|
||||
}
|
||||
.input-width1{
|
||||
width: calc(100% - 60px)!important;
|
||||
}
|
||||
.input-width2{
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -0,0 +1,915 @@
|
|||
<template>
|
||||
<div class="report-wrapper">
|
||||
<el-card v-loading="loading" shadow="never">
|
||||
<div slot="header" class="clearfix report-header">
|
||||
<!-- 电子影像病例报告表(eICRF) -->
|
||||
<h3 style="margin:0;padding:0;">{{ $t('trials:readingReport:title:eicrf') }}</h3>
|
||||
<div style="margin-left:auto">
|
||||
<el-switch
|
||||
v-model="isShowDetail"
|
||||
:active-text="$t('trials:readingReport:title:expandDetails')"
|
||||
:inactive-text="$t('trials:readingReport:title:collapseDetails')"
|
||||
style="margin-right:5px;"
|
||||
@change="handleShowDetail"
|
||||
/>
|
||||
<el-button
|
||||
v-if="readingTaskState<2"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="skipTask"
|
||||
>
|
||||
<!-- 跳过 -->
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="readingTaskState<2"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="getReportInfo(false)"
|
||||
>
|
||||
<!-- 刷新 -->
|
||||
{{ $t('trials:readingReport:button:refresh') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="readingTaskState<2 && criterionType !== 10"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="handleSave(true)"
|
||||
>
|
||||
<!-- 保存 -->
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="readingTaskState<2"
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="beforeLeave"
|
||||
>
|
||||
<!-- 提交 -->
|
||||
{{ $t('common:button:submit') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div ref="tableWrapper" style="height:100%;overflow-y: auto;">
|
||||
<el-table
|
||||
v-if="height"
|
||||
ref="reportList"
|
||||
:data="taskQuestions"
|
||||
row-key="Id"
|
||||
border
|
||||
:expand-row-keys="expandedRows"
|
||||
:height="height"
|
||||
:tree-props="{children: 'Childrens', hasChildren: 'hasChildren'}"
|
||||
size="mini"
|
||||
>
|
||||
<el-table-column
|
||||
prop=""
|
||||
label=""
|
||||
show-overflow-tooltip
|
||||
width="350px"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="scope.row.QuestionName" :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) ? '#f66' : '#fff'}">{{ scope.row.QuestionName }}</span>
|
||||
<span
|
||||
v-else
|
||||
style="font-weight: bold;font-size: 16px;color: #f44336;"
|
||||
>
|
||||
{{ language==='en'?scope.row.GroupEnName:scope.row.GroupName }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-for="task in visitTaskList"
|
||||
:key="task.VisitTaskId"
|
||||
prop="date"
|
||||
|
||||
show-overflow-tooltip
|
||||
width="150px"
|
||||
>
|
||||
<template slot="header">
|
||||
<div v-if="task.IsCurrentTask">
|
||||
<div>
|
||||
{{ task.BlindName }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
<div>
|
||||
{{ task.BlindName }}
|
||||
<el-button type="text" size="small" @click="previewDicoms(task)">
|
||||
<span class="el-icon-view" />
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<span :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) || (scope.row.QuestionMark === 12) || scope.row.HighlightAnswerList.includes(`${scope.row.Answers[task.VisitTaskId]}`) ? '#f66' : '#fff'}">
|
||||
<template v-if="task.VisitTaskId === visitTaskId && readingTaskState < 2 && [13,14,15,42].includes(scope.row.QuestionType)">
|
||||
<!-- 是否存在疾病(基线时可修改) -->
|
||||
<template v-if="task.IsBaseLine && scope.row.QuestionType=== 15">
|
||||
<el-select
|
||||
v-if="scope.row.Type==='select' && scope.row.DictionaryCode"
|
||||
v-model="currentExistDisease"
|
||||
size="mini"
|
||||
@change="handleExistDiseaseChange"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</el-select>
|
||||
</template>
|
||||
<!-- 整体肿瘤评估(非基线可修改) -->
|
||||
<template v-else-if="!task.IsBaseLine && (scope.row.QuestionType=== 13 || scope.row.QuestionType=== 42)">
|
||||
<el-select
|
||||
v-if="scope.row.Type==='select' && scope.row.DictionaryCode"
|
||||
v-model="currentEvaluateResult"
|
||||
size="mini"
|
||||
@change="handleEvaluateResultChange"
|
||||
>
|
||||
<template v-if="criterionType === 1 && tLesionCount">
|
||||
<el-option
|
||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
||||
v-show="(!task.IsBaseLine && item.value > -1) && (task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1) && (item.value !== 1 && item.value !== 3)"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="criterionType === 1 && ntLesionCount">
|
||||
<el-option
|
||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
||||
v-show="(!task.IsBaseLine && item.value > -1) && (task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1) && (item.value !== 1)"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="item of $d[ scope.row.DictionaryCode]"
|
||||
v-show="(!task.IsBaseLine && item.value > -1) && (task.CrterionDictionaryGroup.indexOf(item.raw.CrterionDictionaryGroup) > -1)"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
<!-- <template v-else-if="task.IsBaseLine && scope.row.QuestionType=== 13">
|
||||
{{ $fd(scope.row.DictionaryCode, currentEvaluateResult) }}
|
||||
</template> -->
|
||||
<!-- 访视点备注(是否存在疾病与系统不一致或者整体肿瘤评估与系统不一致时,必填) -->
|
||||
<!-- tumorEvaluate && task.VisitTaskId === visitTaskId && scope.row.QuestionType=== 14 && (currentEvaluateResult !== tumorEvaluate || currentExistDisease !== isExistDisease) -->
|
||||
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.QuestionType=== 14 ">
|
||||
<!-- v-if="tumorEvaluate && (currentEvaluateResult !== tumorEvaluate || currentExistDisease !== isExistDisease)" -->
|
||||
<template>
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="scope.row.Type==='input'"
|
||||
v-model="currentTaskReason"
|
||||
size="mini"
|
||||
@change="evaluateReasonChange"
|
||||
/>
|
||||
<el-input
|
||||
v-else-if="scope.row.Type==='textarea'"
|
||||
v-model="currentTaskReason"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
size="mini"
|
||||
maxlength="500"
|
||||
@change="evaluateReasonChange"
|
||||
/>
|
||||
<!-- 系统评估结果为:xxx,与当前调整的结果不一致,请填写调整原因 -->
|
||||
<p v-if="currentEvaluateResult !== tumorEvaluate" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;" v-html="getWarningText()" />
|
||||
<p v-else-if="currentExistDisease !== isExistDisease" style="width: 140px;padding:0 2px;white-space: normal;word-break: break-all;word-wrap: break-word;">{{ $t('trials:readingReport:title:sysEvaluationRes') }}<span style="color:red">{{ $fd('ExistDisease',isExistDisease) }}</span>{{ $t('trials:readingReport:message:msg1') }}
|
||||
</p>
|
||||
</template>
|
||||
<!-- <template v-else>
|
||||
<span>{{ currentTaskReason }}</span>
|
||||
</template> -->
|
||||
|
||||
</template>
|
||||
<template v-else-if="scope.row.DictionaryCode">
|
||||
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ scope.row.Answers[task.VisitTaskId] }}
|
||||
</template>
|
||||
</template>
|
||||
|
||||
<template v-else-if="scope.row.QuestionType=== 15">
|
||||
<el-tooltip v-if="getAnswerInfo(scope.row.Answer,task.VisitTaskId,'IsGlobalChange')" :content="`${$t('trials:reading:warnning:msg55')}${$fd(scope.row.DictionaryCode, getAnswerInfo(scope.row.Answer,task.VisitTaskId,'GlobalChangeAnswer'))}`" placement="top" effect="light">
|
||||
<span style="color:red;"> {{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
||||
</template>
|
||||
|
||||
<template v-else-if="scope.row.QuestionType=== 13 || scope.row.QuestionType=== 42">
|
||||
<el-tooltip v-if="getAnswerInfo(scope.row.Answer,task.VisitTaskId,'IsGlobalChange')" :content="`${$t('trials:reading:warnning:msg55')}${$fd(scope.row.DictionaryCode, getAnswerInfo(scope.row.Answer,task.VisitTaskId,'GlobalChangeAnswer'))}`" placement="top" effect="light">
|
||||
<span style="color:red;"> {{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
||||
</el-tooltip>
|
||||
<span v-else>{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}</span>
|
||||
</template>
|
||||
<template v-else-if="scope.row.QuestionType=== 22">
|
||||
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? $t('trials:readingReport:title:unknow') : scope.row.Answers[task.VisitTaskId] }}
|
||||
</template>
|
||||
|
||||
<template v-else-if="scope.row.DictionaryCode">
|
||||
{{ $fd(scope.row.DictionaryCode, scope.row.Answers[task.VisitTaskId]) }}
|
||||
</template>
|
||||
<template v-else-if="criterionType === 10">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]}` }}
|
||||
</template>
|
||||
<template v-else-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
{{ `${scope.row.Answers[task.VisitTaskId]}` }}
|
||||
<span v-if="scope.row.Answers[task.VisitTaskId] !== 'NA' && !isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))">{{ `${$fd('ValueUnit',scope.row.Unit)}` }}</span>
|
||||
</template>
|
||||
<template v-else-if="scope.row.ValueType === 2">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]}%` }}
|
||||
</template>
|
||||
<template v-else-if="scope.row.Answers && scope.row.Answers.hasOwnProperty(task.VisitTaskId)">
|
||||
{{ scope.row.Answers[task.VisitTaskId] }}
|
||||
</template>
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</el-card>
|
||||
<!-- 附加评估 -->
|
||||
<el-dialog
|
||||
v-if="additionalAssessmentsDig.visible"
|
||||
:visible.sync="additionalAssessmentsDig.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="additionalAssessmentsDig.title"
|
||||
width="600px"
|
||||
>
|
||||
<AdditionalAssessment
|
||||
:questions="assessmentQuestions"
|
||||
:visit-task-id="visitTaskId"
|
||||
@close="additionalAssessmentsDig.visible = false"
|
||||
@sign="sign"
|
||||
/>
|
||||
</el-dialog>
|
||||
<!-- 签名框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div slot="title">
|
||||
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
||||
<span style="font-size:12px;margin-left:5px">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
|
||||
</div>
|
||||
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getTaskAdditionalQuestion } from '@/api/trials'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import { getAutoCutNextTask } from '@/api/user'
|
||||
import const_ from '@/const/sign-code'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
import AdditionalAssessment from '@/views/trials/trials-panel/reading/dicoms/components/AdditionalAssessment'
|
||||
export default {
|
||||
name: 'ReportPage',
|
||||
components: { SignForm, AdditionalAssessment },
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
visitTaskList: [],
|
||||
taskQuestions: [],
|
||||
loading: false,
|
||||
answers: [],
|
||||
readingTaskState: 2,
|
||||
tumorEvaluate: null,
|
||||
currentEvaluateResult: null,
|
||||
isExistDisease: null,
|
||||
currentExistDisease: null,
|
||||
currentTaskReason: '',
|
||||
answerArr: [],
|
||||
questions: [],
|
||||
isShowDetail: false,
|
||||
criterionType: 0,
|
||||
height: 0,
|
||||
additionalAssessmentsDig: { visible: false, title: this.$t('trials:trials-panel:setting:reading-unit:TrialCriterionAdditionalAssessmentTypeList') },
|
||||
assessmentQuestions: [],
|
||||
tLesionCount: null,
|
||||
ntLesionCount: null,
|
||||
openWindow: null,
|
||||
expandedRows: [],
|
||||
taskInfo: {},
|
||||
visitTaskId: '',
|
||||
isBaselineTask: false
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
watch: {
|
||||
taskQuestions() {
|
||||
this.$nextTick(() => {
|
||||
this.getTableHeight()
|
||||
this.$refs.reportList && this.$refs.reportList.doLayout()
|
||||
this.setScrollTop()
|
||||
})
|
||||
}
|
||||
},
|
||||
created() { this.getTableHeight() },
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
this.criterionType = this.taskInfo.CriterionType
|
||||
this.visitTaskId = this.taskInfo.VisitTaskId
|
||||
this.isBaselineTask = this.taskInfo.IsBaseLine
|
||||
window.addEventListener('resize', () => {
|
||||
this.handleResize()
|
||||
this.setScrollTop()
|
||||
})
|
||||
this.getReportInfo()
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
myConfirm(msg) {
|
||||
return new Promise(resolve => {
|
||||
this.$confirm(msg, {
|
||||
type: 'warning',
|
||||
showCancelButton: true
|
||||
}).then(() => {
|
||||
resolve(true)
|
||||
}).catch(() => {
|
||||
resolve(false)
|
||||
})
|
||||
})
|
||||
},
|
||||
async beforeLeave() {
|
||||
this.handleConfirm()
|
||||
},
|
||||
getAnswerInfo(answerArr, visitTaskId, prop) {
|
||||
var i = answerArr.findIndex(i => i.VisitTaskId === visitTaskId)
|
||||
if (i === -1) return ''
|
||||
var val = answerArr[i][prop]
|
||||
return isNaN(parseInt(val)) ? val : parseInt(val)
|
||||
},
|
||||
getTableHeight() {
|
||||
this.height = window.innerHeight - 170
|
||||
},
|
||||
async getReportInfo(IsCalculate) {
|
||||
this.loading = true
|
||||
try {
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.$router.currentRoute.query.trialId,
|
||||
IsCalculate: IsCalculate !== false
|
||||
}
|
||||
const res = await getReadingReportEvaluation(params)
|
||||
if (res.IsSuccess) {
|
||||
this.readingTaskState = res.Result.ReadingTaskState
|
||||
this.tumorEvaluate = res.Result.CalculateResult && res.Result.CalculateResult.TumorEvaluate ? parseInt(res.Result.CalculateResult.TumorEvaluate) : null
|
||||
this.isExistDisease = res.Result.CalculateResult && res.Result.CalculateResult.IsExistDisease ? parseInt(res.Result.CalculateResult.IsExistDisease) : null
|
||||
this.answerArr = []
|
||||
this.questions = res.Result.TaskQuestions.concat()
|
||||
this.visitTaskList = res.Result.VisitTaskList
|
||||
var taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null, null)
|
||||
this.taskQuestions = []
|
||||
taskQuestions.forEach(item => {
|
||||
this.$set(this.taskQuestions, this.taskQuestions.length, item)
|
||||
})
|
||||
const tLesion = res.Result.LesionCountList.find(i => i.LesionType === 0)
|
||||
this.tLesionCount = tLesion ? tLesion.Count : 0
|
||||
const ntLesion = res.Result.LesionCountList.find(i => i.LesionType === 1)
|
||||
this.ntLesionCount = ntLesion ? ntLesion.Count : 0
|
||||
this.setScrollTop()
|
||||
}
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
setScrollTop(a) {
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
if (this.$refs.reportList) {
|
||||
this.getTableHeight()
|
||||
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
|
||||
}
|
||||
})
|
||||
}, 50)
|
||||
},
|
||||
getQuestions(questions, isNTFilterLength, lesionType, isLymphNodes) {
|
||||
const arr = []
|
||||
if (questions.length !== 0) {
|
||||
questions.forEach((item) => {
|
||||
if (this.criterionType === 21) {
|
||||
if (!this.isShowDetail) {
|
||||
if (!item.RowId) {
|
||||
this.expandedRows.push(item.Id)
|
||||
}
|
||||
} else {
|
||||
this.expandedRows.push(item.Id)
|
||||
}
|
||||
|
||||
} else {
|
||||
this.expandedRows.push(item.Id)
|
||||
}
|
||||
// 过滤病灶标识 病灶名称 部位 器官 位置 是否淋巴结
|
||||
// 非靶病灶和新病灶 过滤长径和短径信息
|
||||
// 非淋巴结靶病灶 过滤短径
|
||||
|
||||
lesionType = item.LesionType
|
||||
var filterArr = [7]
|
||||
// 0:靶病灶、 5:新靶病灶
|
||||
// 1:非靶病灶、2:新病灶、6:新非靶病灶、7:其它既往新病灶、8:触发irecisit后的新病灶
|
||||
// 0:长径,1:短径,2:是否淋巴结,3:自增ID,4:病灶名称,5:所在器官,6:所在位置,7:状态,8:所在部位,10:部位描述
|
||||
// 1105:是否可测量,1106:肝脏分段
|
||||
if ((item.LesionType === 1 || item.LesionType === 2 || item.LesionType === 6 || item.LesionType === 7 || item.LesionType === 8) && isNTFilterLength) {
|
||||
filterArr = [0, 1, 3, 4, 5, 6, 2, 8, 10, 7, 1105]
|
||||
} else {
|
||||
filterArr = [3, 4, 5, 6, 2, 8, 10, 7, 1106, 1105]
|
||||
}
|
||||
if ((lesionType === 0 || lesionType === 5) && isLymphNodes === 0 && !this.isShowDetail && (this.criterionType === 1 || this.criterionType === 3 || this.criterionType === 17)) {
|
||||
filterArr.push(1)
|
||||
}
|
||||
|
||||
if (isLymphNodes === 0) {
|
||||
filterArr.push(1)
|
||||
}
|
||||
if (!(filterArr.includes(item.QuestionMark))) {
|
||||
const obj = item
|
||||
obj.Answers = {}
|
||||
if (item.RowIndex > 0) {
|
||||
try {
|
||||
var idx = item.Childrens.findIndex(i => i.QuestionMark === 8)
|
||||
var idxLoc = item.Childrens.findIndex(i => i.QuestionMark === 10)
|
||||
var state = item.Childrens.findIndex(i => i.QuestionMark === 7)
|
||||
if (idx > -1) {
|
||||
if (item.Childrens[idx].Answer.length > 0) {
|
||||
var k = item.Childrens[idx].Answer.findIndex(v => v.Answer !== '')
|
||||
var part = ''
|
||||
if (obj.IsCanEditPosition) {
|
||||
part = `${item.Childrens[idx].Answer[k].Answer}--${item.Childrens[idxLoc].Answer[k].Answer}`
|
||||
} else {
|
||||
part = `${item.Childrens[idx].Answer[k].Answer}`
|
||||
}
|
||||
if (item.SplitOrMergeLesionName && k > -1) {
|
||||
// obj.QuestionName = `${obj.QuestionName} --${part} (Split from ${item.SplitOrMergeLesionName})`
|
||||
obj.QuestionName = `${obj.QuestionName} --${part}`
|
||||
var Answers = {}
|
||||
if (state >= 0) {
|
||||
this.visitTaskList.forEach(v => {
|
||||
const o = item.Childrens[state].Answer.find(v1 => {
|
||||
return v1.VisitTaskId === v.VisitTaskId
|
||||
})
|
||||
if (o) {
|
||||
Answers[o.VisitTaskId] = this.$fd(item.Childrens[state].DictionaryCode, parseInt(o.Answer))
|
||||
}
|
||||
})
|
||||
}
|
||||
this.$set(obj, 'Answers', Answers)
|
||||
// obj.QuestionName = `${obj.QuestionName} `
|
||||
} else if (!item.SplitOrMergeLesionName && k > -1) {
|
||||
obj.QuestionName = `${obj.QuestionName}--${part}`
|
||||
const Answers = {}
|
||||
if (state >= 0) {
|
||||
this.visitTaskList.forEach(v => {
|
||||
const o = item.Childrens[state].Answer.find(v1 => {
|
||||
return v1.VisitTaskId === v.VisitTaskId
|
||||
})
|
||||
if (o) {
|
||||
Answers[o.VisitTaskId] = this.$fd(item.Childrens[state].DictionaryCode, parseInt(o.Answer))
|
||||
}
|
||||
})
|
||||
}
|
||||
this.$set(obj, 'Answers', Answers)
|
||||
// obj.QuestionName = `${obj.QuestionName} `
|
||||
} else {
|
||||
obj.QuestionName = `${obj.QuestionName} `
|
||||
}
|
||||
if (item.ReportMark) {
|
||||
obj.QuestionName = `${obj.QuestionName} (${item.ReportMark})`
|
||||
}
|
||||
|
||||
if (this.criterionType === 1 || this.criterionType === 3 || this.criterionType === 17) {
|
||||
var idxLymphNode = item.Childrens.findIndex(i => i.QuestionMark === 2)
|
||||
if (idxLymphNode > -1) {
|
||||
isLymphNodes = item.Childrens[idxLymphNode].Answer[k].Answer ? parseInt(item.Childrens[idxLymphNode].Answer[k].Answer) : null
|
||||
item.Childrens.forEach(v => {
|
||||
this.$set(v, 'isLymphNodes', isLymphNodes)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.criterionType === 21) {
|
||||
var liverSegmentIdx = item.Childrens.findIndex(i => i.QuestionMark === 1106)
|
||||
if (liverSegmentIdx > -1) {
|
||||
if (item.Childrens[liverSegmentIdx].Answer.length > 0) {
|
||||
let v = item.Childrens[liverSegmentIdx].Answer[0].Answer
|
||||
obj.QuestionName = this.$fd(item.Childrens[liverSegmentIdx].DictionaryCode, parseInt(v))
|
||||
let Answers = {}
|
||||
let mean = item.Childrens.findIndex(i => i.QuestionMark === 1104)
|
||||
if (mean > -1) {
|
||||
this.visitTaskList.forEach(v => {
|
||||
const o = item.Childrens[mean].Answer.find(v1 => {
|
||||
return v1.VisitTaskId === v.VisitTaskId
|
||||
})
|
||||
if (o) {
|
||||
Answers[o.VisitTaskId] = isNaN(parseFloat(o.Answer)) ? o.Answer : `${o.Answer}%`
|
||||
}
|
||||
})
|
||||
}
|
||||
this.$set(obj, 'Answers', Answers)
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
item.Answer.forEach(i => {
|
||||
if (item.DictionaryCode) {
|
||||
obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
||||
} else {
|
||||
obj.Answers[i.VisitTaskId] = i.Answer
|
||||
}
|
||||
})
|
||||
if (item.QuestionType === 15) {
|
||||
this.currentExistDisease = obj.Answers[this.visitTaskId]
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 15 })
|
||||
}
|
||||
if (item.QuestionType === 13 || item.QuestionType === 42) {
|
||||
this.currentEvaluateResult = obj.Answers[this.visitTaskId]
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: item.QuestionType })
|
||||
}
|
||||
if (item.QuestionType === 14) {
|
||||
this.currentTaskReason = obj.Answers[this.visitTaskId]
|
||||
this.answerArr.push({ id: item.QuestionId, answer: obj.Answers[this.visitTaskId], questionType: 14 })
|
||||
}
|
||||
if (item.Childrens.length >= 1) {
|
||||
obj.Childrens = this.getQuestions(item.Childrens, isNTFilterLength, lesionType, isLymphNodes)
|
||||
}
|
||||
arr.push(obj)
|
||||
}
|
||||
})
|
||||
}
|
||||
return arr
|
||||
},
|
||||
handleShowDetail(val) {
|
||||
this.getReportInfo()
|
||||
// this.taskQuestions = this.getQuestions(res.Result.TaskQuestions, !this.isShowDetail, null)
|
||||
},
|
||||
handleExistDiseaseChange(val) {
|
||||
// this.currentExistDisease = parseInt(val)
|
||||
if (val === this.isExistDisease && this.tumorEvaluate === this.currentEvaluateResult) {
|
||||
this.currentTaskReason = ''
|
||||
this.evaluateReasonChange('')
|
||||
}
|
||||
this.currentTaskReason = ''
|
||||
this.evaluateReasonChange('')
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 15)
|
||||
if (idx > -1) {
|
||||
this.answerArr[idx].answer = val
|
||||
}
|
||||
},
|
||||
handleEvaluateResultChange(val) {
|
||||
// this.currentEvaluateResult = parseInt(val)
|
||||
if (val === this.tumorEvaluate && this.isExistDisease === this.currentExistDisease) {
|
||||
this.currentTaskReason = ''
|
||||
this.evaluateReasonChange('')
|
||||
}
|
||||
this.currentTaskReason = ''
|
||||
this.evaluateReasonChange('')
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 13 || i.questionType === 42)
|
||||
if (idx > -1) {
|
||||
this.answerArr[idx].answer = val
|
||||
}
|
||||
this.setScrollTop()
|
||||
},
|
||||
|
||||
evaluateReasonChange(val) {
|
||||
var idx = this.answerArr.findIndex(i => i.questionType === 14)
|
||||
if (idx > -1) {
|
||||
this.answerArr[idx].answer = val
|
||||
}
|
||||
},
|
||||
async handleConfirm() {
|
||||
this.loading = true
|
||||
try {
|
||||
await this.handleSave(false)
|
||||
await verifyVisitTaskQuestions({ visitTaskId: this.visitTaskId })
|
||||
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
var isBaseline = this.visitTaskList[i].IsBaseLine
|
||||
if (isBaseline) {
|
||||
const res = await getTaskAdditionalQuestion({ visitTaskId: this.visitTaskId })
|
||||
this.assessmentQuestions = res.Result
|
||||
if (this.assessmentQuestions.length > 0) {
|
||||
// 打开附加评估框
|
||||
this.additionalAssessmentsDig.visible = true
|
||||
} else {
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
}
|
||||
} else {
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
}
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
}
|
||||
},
|
||||
sign() {
|
||||
this.additionalAssessmentsDig.visible = false
|
||||
this.$nextTick(() => {
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
})
|
||||
},
|
||||
handleResize() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportList && this.$refs.reportList.doLayout()
|
||||
})
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
async signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
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']) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
|
||||
this.signVisible = false
|
||||
// window.location.reload()
|
||||
// window.opener.postMessage('refreshTaskList', window.location)
|
||||
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
this.$emit('setReadingTaskState', 2)
|
||||
const res = await getAutoCutNextTask()
|
||||
var 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)
|
||||
})
|
||||
}
|
||||
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
}
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
previewDicoms(task) {
|
||||
if (this.openWindow) {
|
||||
this.openWindow.close()
|
||||
}
|
||||
var token = getToken()
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
// var subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
var subjectCode = localStorage.getItem('subjectCode')
|
||||
var subjectId = this.$router.currentRoute.query.subjectId
|
||||
var trialId = this.$router.currentRoute.query.trialId
|
||||
var isReadingTaskViewInOrder = this.$router.currentRoute.query.isReadingTaskViewInOrder
|
||||
var criterionType = this.$router.currentRoute.query.criterionType
|
||||
var readingTool = this.$router.currentRoute.query.readingTool
|
||||
var path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
const routeData = this.$router.resolve({ path })
|
||||
this.openWindow = window.open(routeData.href, '_blank')
|
||||
},
|
||||
handleSave(isPrompt) {
|
||||
return new Promise(async(resolve, reject) => {
|
||||
var isBeill
|
||||
var evaluateResult = ''
|
||||
var evaluateAjustReason = ''
|
||||
this.answers = []
|
||||
var isExistEvaluateResult = false
|
||||
this.answerArr.map(item => {
|
||||
if (item.questionType === 13 || item.questionType === 42) {
|
||||
evaluateResult = item.answer
|
||||
isExistEvaluateResult = true
|
||||
}
|
||||
if (item.questionType === 14) {
|
||||
evaluateAjustReason = item.answer
|
||||
}
|
||||
if (item.questionType === 15) {
|
||||
isBeill = item.answer
|
||||
}
|
||||
this.answers.push({ id: item.id, answer: item.answer })
|
||||
})
|
||||
console.log(this.currentExistDisease, this.isExistDisease, evaluateAjustReason, isBeill)
|
||||
if (this.currentExistDisease !== this.isExistDisease && !evaluateAjustReason) {
|
||||
this.$confirm(this.$t('trials:readingReport:message:msg2'), {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
if (isExistEvaluateResult && (evaluateResult === null && !this.isBaselineTask)) {
|
||||
// 请将疗效评估信息填写完整
|
||||
this.$confirm(this.$t('trials:readingReport:message:msg2'), {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
if (isExistEvaluateResult && (evaluateResult !== this.tumorEvaluate) && !evaluateAjustReason) {
|
||||
// 请填写整体评估调整原因
|
||||
this.$confirm(this.$t('trials:readingReport:message:msg3'), {
|
||||
type: 'warning',
|
||||
showCancelButton: false,
|
||||
callback: action => {}
|
||||
})
|
||||
resolve()
|
||||
return
|
||||
}
|
||||
this.loading = true
|
||||
try {
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
answers: this.answers
|
||||
}
|
||||
const res = await changeDicomReadingQuestionAnswer(params)
|
||||
if (res.IsSuccess && isPrompt) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
this.loading = false
|
||||
resolve()
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
reject()
|
||||
}
|
||||
})
|
||||
},
|
||||
getWarningText() {
|
||||
var sysRes = ''
|
||||
var curRes = ''
|
||||
if (this.CriterionType === 2) {
|
||||
sysRes = this.$fd('ImagingOverallAssessment_Lugano', this.tumorEvaluate)
|
||||
curRes = this.$fd('ImagingOverallAssessment_Lugano', this.currentEvaluateResult)
|
||||
} else {
|
||||
sysRes = this.$fd('OverallAssessment', this.tumorEvaluate)
|
||||
curRes = this.$fd('OverallAssessment', this.currentEvaluateResult)
|
||||
}
|
||||
if (!curRes) {
|
||||
return ''
|
||||
}
|
||||
const msg = this.$t('trials:readingReport:message:msg9').replace('xxx', '<font color="red">' + sysRes + '</font>').replace('yyy', '<font color="red">' + curRes + '</font>')
|
||||
return msg
|
||||
},
|
||||
async skipTask() {
|
||||
try {
|
||||
// 是否确认跳过?
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:readingReport:message:skipConfirm'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
this.loading = true
|
||||
const res = await setSkipReadingCache({ visitTaskId: this.visitTaskId })
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
window.location.reload()
|
||||
}
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.report-wrapper{
|
||||
|
||||
height: 100%;
|
||||
padding: 10px 0px;
|
||||
// background-color: #fff;
|
||||
background-color: #000;
|
||||
::-webkit-scrollbar {
|
||||
width: 7px;
|
||||
height: 7px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
.report-header{
|
||||
display: flex;
|
||||
}
|
||||
.el-card{
|
||||
display:flex;flex-direction: column;height: 100%;
|
||||
background-color: #000;
|
||||
color: #ffffff;
|
||||
border:none;
|
||||
::v-deep .el-card__body{
|
||||
flex: 1;
|
||||
}
|
||||
}
|
||||
|
||||
// ::v-deep .el-table__cell{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
// }
|
||||
// ::v-deep .el-table{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
// }
|
||||
// ::v-deep .el-table__cell{
|
||||
// background-color: #000;
|
||||
// color: #ffffff;
|
||||
// }
|
||||
|
||||
::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-card__header{
|
||||
border: none;
|
||||
padding: 10px;
|
||||
}
|
||||
}
|
||||
::v-deep .el-switch__label{
|
||||
color:#fff;
|
||||
}
|
||||
::v-deep .el-switch__label.is-active{
|
||||
color: #428bca;
|
||||
}
|
||||
.colorOfRed{
|
||||
color: #f66;
|
||||
}
|
||||
</style>
|
|
@ -22,13 +22,13 @@
|
|||
v-if="!study.IsCriticalSequence"
|
||||
class="dicom-desc"
|
||||
>
|
||||
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
||||
<template v-if="taskInfo && taskInfo.IsShowStudyName">
|
||||
<div style="text-overflow: ellipsis;overflow: hidden;">
|
||||
<span :title="study.StudyCode">{{ study.StudyCode }}</span>
|
||||
<span v-if="study.StudyName" :title="study.StudyName" style="margin-left: 5px;">{{ study.StudyName }}</span>
|
||||
<span v-else :title="study.Modalities" style="margin-left: 5px;">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
<div style="text-overflow: ellipsis;overflow: hidden;" v-if="study.StudyName" >
|
||||
<div v-if="study.StudyName" style="text-overflow: ellipsis;overflow: hidden;">
|
||||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -38,7 +38,7 @@
|
|||
<span :title="study.Modalities">{{ `${study.Modalities} (${study.SeriesCount})` }}</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
</div>
|
||||
<div v-else>
|
||||
<!-- 关键序列 -->
|
||||
|
@ -64,14 +64,14 @@
|
|||
crossorigin="anonymous"
|
||||
/>
|
||||
</div>
|
||||
<div class="series-text" >
|
||||
<div class="text-desc" v-if="!study.IsCriticalSequence" :title="series.SeriesNumber">
|
||||
<div class="series-text">
|
||||
<div v-if="!study.IsCriticalSequence" class="text-desc" :title="series.SeriesNumber">
|
||||
#{{ series.SeriesNumber }}
|
||||
</div>
|
||||
<div class="text-desc" v-if="series.Description" :title="series.Description">
|
||||
<div v-if="series.Description" class="text-desc" :title="series.Description">
|
||||
{{ series.Description }}
|
||||
</div>
|
||||
<div class="text-desc" v-if="series.SliceThickness && !study.IsCriticalSequence">
|
||||
<div v-if="series.SliceThickness && !study.IsCriticalSequence" class="text-desc">
|
||||
T: {{ parseFloat(series.SliceThickness).toFixed(digitPlaces) }}
|
||||
</div>
|
||||
<div class="text-desc">
|
||||
|
@ -80,7 +80,7 @@
|
|||
</span>
|
||||
<span v-show="series.LoadedImageCount >= series.InstanceCount">{{ series.Modality }}: {{ series.InstanceCount }} image</span>
|
||||
</div>
|
||||
<div v-show="series.IsBeMark">
|
||||
<div v-show="annotations.findIndex(v=>v.seriesId === series.Id && v.MeasureData) > -1">
|
||||
<i class="el-icon-star-on" style="font-size: 16px;color: #ff5722;" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -116,14 +116,16 @@ export default {
|
|||
activeSeriesIndex: -1,
|
||||
taskInfo: null,
|
||||
studyList: [],
|
||||
annotations: [],
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.studyList = this.visitTaskInfo.StudyList
|
||||
this.annotations = this.visitTaskInfo.Annotations
|
||||
if (this.studyList.length === 0) return
|
||||
this.$nextTick(() => {
|
||||
this.activeStudy(this.studyList[0].StudyId)
|
||||
|
@ -142,22 +144,22 @@ export default {
|
|||
setSeriesActive(studyIndex, seriesIndex) {
|
||||
this.activeStudyIndex = studyIndex
|
||||
this.activeSeriesIndex = seriesIndex
|
||||
let studyId = this.studyList[studyIndex].StudyId
|
||||
const studyId = this.studyList[studyIndex].StudyId
|
||||
if (!studyId) return
|
||||
this.activeStudy(studyId)
|
||||
},
|
||||
getPreviousOrNextSeries(type, series) {
|
||||
let seriseList = this.studyList.map(s => s.SeriesList).flat()
|
||||
let i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId)
|
||||
const seriseList = this.studyList.map(s => s.SeriesList).flat()
|
||||
const i = seriseList.findIndex(i => i.Id === series.Id && i.StudyId === series.StudyId)
|
||||
if (i === -1) return
|
||||
let newIndex = null
|
||||
if (type === -1) {
|
||||
newIndex = i === 0 ? i : i - 1
|
||||
} else {
|
||||
newIndex = i >= seriseList.length - 1 ? i : i +1
|
||||
newIndex = i >= seriseList.length - 1 ? i : i + 1
|
||||
}
|
||||
let studyIndex = seriseList[newIndex].StudyIndex
|
||||
let seriesIndex = seriseList[newIndex].SeriesIndex
|
||||
const studyIndex = seriseList[newIndex].StudyIndex
|
||||
const seriesIndex = seriseList[newIndex].SeriesIndex
|
||||
this.setSeriesActive(studyIndex, seriesIndex)
|
||||
this.activeSeries(seriseList[newIndex], seriesIndex, studyIndex)
|
||||
}
|
||||
|
|
|
@ -1,22 +1,23 @@
|
|||
<template>
|
||||
<div
|
||||
<div
|
||||
ref="viewport"
|
||||
class="viewport-wrapper"
|
||||
@mouseup="sliderMouseup"
|
||||
@mousemove="sliderMousemove"
|
||||
@mouseleave="sliderMouseleave"
|
||||
>
|
||||
<div class="left-top-text" v-if="series && taskInfo">
|
||||
<div v-if="series && taskInfo" class="left-top-text">
|
||||
<div
|
||||
v-if="taskInfo.IsExistsClinicalData"
|
||||
class="cd-info"
|
||||
:title="$t('trials:reading:button:clinicalData')"
|
||||
>
|
||||
<svg-icon
|
||||
style="cursor: pointer;"
|
||||
icon-class="documentation"
|
||||
class="svg-icon"
|
||||
@click.stop="viewCD(series.TaskInfo.VisitTaskId)" />
|
||||
<svg-icon
|
||||
style="cursor: pointer;"
|
||||
icon-class="documentation"
|
||||
class="svg-icon"
|
||||
@click.stop="viewCD(series.TaskInfo.VisitTaskId)"
|
||||
/>
|
||||
</div>
|
||||
<h2
|
||||
v-if="taskInfo.IsReadingShowSubjectInfo"
|
||||
|
@ -26,7 +27,7 @@
|
|||
</h2>
|
||||
<div>Series: #{{ series.SeriesNumber }}</div>
|
||||
<div>Image: #{{ `${series.SliceIndex + 1}/${series.ImageIds.length}` }}</div>
|
||||
<div>{{series.Modality}}</div>
|
||||
<div>{{ series.Modality }}</div>
|
||||
</div>
|
||||
<div
|
||||
v-if="series && taskInfo && taskInfo.IsReadingTaskViewInOrder === 1"
|
||||
|
@ -54,10 +55,10 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-top-text" v-if="series">
|
||||
<div v-if="series" class="right-top-text">
|
||||
<div>{{ series.Description }}</div>
|
||||
</div>
|
||||
<div class="left-bottom-text" v-if="series">
|
||||
<div v-if="series" class="left-bottom-text">
|
||||
<div v-show="mousePosition.index.length > 0">
|
||||
Pos: {{ mousePosition.index[0] }}, {{ mousePosition.index[1] }}, {{ mousePosition.index[2] }}
|
||||
</div>
|
||||
|
@ -74,7 +75,7 @@
|
|||
W*H: {{ imageInfo.size }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-bottom-text" v-if="series">
|
||||
<div v-if="series" class="right-bottom-text">
|
||||
<div v-show="imageInfo.location">Location: {{ `${Number(imageInfo.location).toFixed(digitPlaces)} mm` }}</div>
|
||||
<div v-show="series.SliceThickness">Slice Thickness: {{ `${Number(series.SliceThickness).toFixed(digitPlaces)} mm` }}</div>
|
||||
<div v-show="imageInfo.wwwc ">WW/WL: {{ imageInfo.wwwc }}</div>
|
||||
|
@ -98,20 +99,20 @@
|
|||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import * as cornerstonejs from '@cornerstonejs/core'
|
||||
// import * as cornerstonejs from '@cornerstonejs/core'
|
||||
import {
|
||||
RenderingEngine,
|
||||
Enums,
|
||||
imageLoader,
|
||||
// RenderingEngine,
|
||||
// Enums,
|
||||
// imageLoader,
|
||||
metaData,
|
||||
getRenderingEngine,
|
||||
eventTarget,
|
||||
// eventTarget,
|
||||
utilities as csUtils
|
||||
} from '@cornerstonejs/core'
|
||||
import * as cornerstoneTools from '@cornerstonejs/tools'
|
||||
import { vec3, mat4 } from 'gl-matrix'
|
||||
import { vec3 } from 'gl-matrix'
|
||||
export default {
|
||||
name: 'Viewport',
|
||||
name: 'ImageViewport',
|
||||
props: {
|
||||
renderingEngineId: {
|
||||
type: String,
|
||||
|
@ -126,7 +127,7 @@ export default {
|
|||
required: true
|
||||
}
|
||||
},
|
||||
data(){
|
||||
data() {
|
||||
return {
|
||||
element: '',
|
||||
series: null,
|
||||
|
@ -137,10 +138,10 @@ export default {
|
|||
isMove: false,
|
||||
height: 0
|
||||
},
|
||||
mousePosition: {
|
||||
index: [],
|
||||
value: null,
|
||||
modalityUnit: '',
|
||||
mousePosition: {
|
||||
index: [],
|
||||
value: null,
|
||||
modalityUnit: '',
|
||||
world: []
|
||||
},
|
||||
imageInfo: {
|
||||
|
@ -160,12 +161,11 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
const digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
this.$nextTick(()=>{
|
||||
this.$nextTick(() => {
|
||||
this.initViewport()
|
||||
})
|
||||
console.log(cornerstonejs)
|
||||
},
|
||||
methods: {
|
||||
initViewport() {
|
||||
|
@ -180,12 +180,12 @@ export default {
|
|||
resizeObserver.observe(this.element)
|
||||
this.element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
this.element.addEventListener('CORNERSTONE_VOI_MODIFIED', this.voiModified)
|
||||
|
||||
|
||||
this.element.addEventListener('CORNERSTONE_TOOLS_MOUSE_MOVE', this.cornerstoneToolsMouseMove)
|
||||
this.element.addEventListener('mouseleave', () => {
|
||||
this.mousePosition.index = []
|
||||
})
|
||||
// console.log(cornerstonejs,cornerstoneTools)
|
||||
this.mousePosition.index = []
|
||||
})
|
||||
// console.log(cornerstoneTools)
|
||||
// element.addEventListener('CORNERSTONE_STACK_NEW_IMAGE', this.stackNewImage)
|
||||
},
|
||||
stackNewImage(e) {
|
||||
|
@ -194,13 +194,14 @@ export default {
|
|||
this.sliderInfo.height = detail.imageIdIndex * 100 / (this.series.ImageIds.length - 1)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
let zoom = viewport.getZoom()
|
||||
const zoom = viewport.getZoom()
|
||||
this.imageInfo.zoom = zoom.toFixed(4)
|
||||
this.imageInfo.size = `${detail.image.columns}*${detail.image.rows}`
|
||||
const imagePlaneModule = metaData.get('imagePlaneModule', detail.imageId)
|
||||
this.imageInfo.location = imagePlaneModule.sliceLocation
|
||||
// this.imageInfo.wwwc = `${Math.round(detail.image.windowWidth)}/${Math.round(detail.image.windowCenter)}`
|
||||
this.getOrientationMarker()
|
||||
this.$emit('renderAnnotations', this.series)
|
||||
},
|
||||
voiModified(e) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
|
@ -239,9 +240,9 @@ export default {
|
|||
}
|
||||
},
|
||||
setMarkers() {
|
||||
let markers = [...this.orientationMarkers]
|
||||
const markers = [...this.orientationMarkers]
|
||||
for (const key in this.markers) {
|
||||
let v = markers.shift(0)
|
||||
const v = markers.shift(0)
|
||||
this.markers[key] = v
|
||||
}
|
||||
},
|
||||
|
@ -258,7 +259,7 @@ export default {
|
|||
this.resetOrientationMarkers()
|
||||
return
|
||||
}
|
||||
let markers = [...this.orientationMarkers]
|
||||
const markers = [...this.orientationMarkers]
|
||||
if (type === 2) {
|
||||
// 垂直翻转
|
||||
this.orientationMarkers[0] = markers[2]
|
||||
|
@ -281,7 +282,7 @@ export default {
|
|||
this.playClipState = isPlay
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
|
||||
if (isPlay) {
|
||||
cornerstoneTools.utilities.cine.playClip(viewport.element, { framesPerSecond })
|
||||
} else {
|
||||
|
@ -291,9 +292,9 @@ export default {
|
|||
scrollPage(type) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
const currentImageIdIndex = viewport.getCurrentImageIdIndex();
|
||||
const numImages = viewport.getImageIds().length;
|
||||
let newImageIdIndex = null;
|
||||
const currentImageIdIndex = viewport.getCurrentImageIdIndex()
|
||||
const numImages = viewport.getImageIds().length
|
||||
let newImageIdIndex = null
|
||||
if (type === 0) {
|
||||
newImageIdIndex = 0
|
||||
} else if (type === -1) {
|
||||
|
@ -301,34 +302,36 @@ export default {
|
|||
} else if (type === 1) {
|
||||
newImageIdIndex = currentImageIdIndex === numImages - 1 ? currentImageIdIndex : currentImageIdIndex + 1
|
||||
} else if (type === 99999) {
|
||||
newImageIdIndex = numImages -1
|
||||
newImageIdIndex = numImages - 1
|
||||
}
|
||||
viewport.setImageIdIndex(newImageIdIndex);
|
||||
viewport.setImageIdIndex(newImageIdIndex)
|
||||
},
|
||||
setZoom(ratio) {
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId);
|
||||
const viewport = renderingEngine.getViewport(this.viewportId);
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
|
||||
const zoom = viewport.getZoom();
|
||||
const zoom = viewport.getZoom()
|
||||
if (ratio > 0) {
|
||||
viewport.setZoom(zoom * 1.05);
|
||||
viewport.setZoom(zoom * 1.05)
|
||||
} else {
|
||||
viewport.setZoom(zoom / 1.05);
|
||||
viewport.setZoom(zoom / 1.05)
|
||||
}
|
||||
viewport.render();
|
||||
viewport.render()
|
||||
},
|
||||
resize(forceFitToWindow) {
|
||||
console.log('resize: ', forceFitToWindow)
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId);
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
renderingEngine.resize(true, forceFitToWindow)
|
||||
},
|
||||
async setSeriesInfo(obj){
|
||||
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description) return
|
||||
this.series = {...obj}
|
||||
async setSeriesInfo(obj, isLocate = false) {
|
||||
if (this.series && obj.Id === this.series.Id && obj.Description === this.series.Description && !isLocate) {
|
||||
obj.SliceIndex = this.series.SliceIndex
|
||||
}
|
||||
this.series = { ...obj }
|
||||
const renderingEngine = getRenderingEngine(this.renderingEngineId)
|
||||
const viewport = renderingEngine.getViewport(this.viewportId)
|
||||
await viewport.setStack(obj.ImageIds, obj.SliceIndex)
|
||||
cornerstoneTools.utilities.stackPrefetch.enable(viewport.element);
|
||||
cornerstoneTools.utilities.stackPrefetch.enable(viewport.element)
|
||||
viewport.render()
|
||||
},
|
||||
cornerstoneToolsMouseMove(e) {
|
||||
|
@ -348,7 +351,7 @@ export default {
|
|||
this.$emit('activeViewport', this.viewportIndex)
|
||||
const num = visitTaskNum + i
|
||||
if (num >= 0 && num <= this.taskInfo.VisitNum) {
|
||||
this.$emit('toggleTaskByViewport', {series: this.series, visitTaskNum: num})
|
||||
this.$emit('toggleTaskByViewport', { series: this.series, visitTaskNum: num })
|
||||
}
|
||||
|
||||
evt.stopImmediatePropagation()
|
||||
|
@ -410,7 +413,7 @@ export default {
|
|||
e.stopImmediatePropagation()
|
||||
e.stopPropagation()
|
||||
e.preventDefault()
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
@ -548,4 +551,4 @@ export default {
|
|||
z-index: 1;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</style>
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
<!-- 阅片 -->
|
||||
<el-tab-pane
|
||||
v-if="taskInfo"
|
||||
ref="readPage"
|
||||
:label="$t('trials:reading:tabTitle:review')"
|
||||
name="read"
|
||||
>
|
||||
|
@ -17,7 +18,10 @@
|
|||
:label="$t('trials:reading:tabTitle:report')"
|
||||
name="report"
|
||||
>
|
||||
<report-page v-if="activeName === 'report'" />
|
||||
<report-page
|
||||
v-if="activeName === 'report'"
|
||||
@setReadingTaskState="setReadingTaskState"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
|
@ -39,6 +43,11 @@ export default {
|
|||
},
|
||||
mounted() {
|
||||
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
|
||||
},
|
||||
methods: {
|
||||
setReadingTaskState(state) {
|
||||
this.$refs['readPage'].setReadingTaskState(state)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
</h4>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-form-item
|
||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
||||
>
|
||||
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='textarea'"
|
||||
v-model="questionForm[question.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
maxlength="500"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-else-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode)"
|
||||
clearable
|
||||
@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="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<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-else-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-radio
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
<template v-else-if="question.TypeValue">
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-else-if="question.Type==='checkbox'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<!-- 数值 -->
|
||||
<template v-else-if="question.Type==='number'">
|
||||
<el-input-number
|
||||
v-if="question.ValueType === 0"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="0"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
</template>
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
<!-- 上传图像 -->
|
||||
<el-upload
|
||||
v-else-if="question.Type==='upload'"
|
||||
action
|
||||
:accept="accept"
|
||||
:limit="question.ImageCount"
|
||||
:on-preview="handlePictureCardPreview"
|
||||
:before-upload="handleBeforeUpload"
|
||||
:http-request="uploadScreenshot"
|
||||
list-type="picture-card"
|
||||
:on-remove="handleRemove"
|
||||
:file-list="fileList"
|
||||
:class="{disabled:fileList.length >= question.ImageCount}"
|
||||
:disabled="readingTaskState >= 2"
|
||||
>
|
||||
<i slot="default" class="el-icon-plus" />
|
||||
<div slot="file" slot-scope="{file}">
|
||||
<img
|
||||
class="el-upload-list__item-thumbnail"
|
||||
:src="OSSclientConfig.basePath + file.url"
|
||||
alt=""
|
||||
>
|
||||
<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>
|
||||
</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">
|
||||
加载中<span class="dot">...</span>
|
||||
</div>
|
||||
</el-image>
|
||||
</el-dialog>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<question-form-item
|
||||
v-for="(item) in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
:visitTaskId="visitTaskId"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
// import { uploadReadingAnswerImage } from '@/api/trials'
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'QuestionFormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: '',
|
||||
urls: [],
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
// console.log(v)
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
let digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
} else {
|
||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
::v-deep .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start;
|
||||
}
|
||||
::v-deep .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
::v-deep .el-input-group__append, .el-input-group__prepend{
|
||||
padding: 0 10px;
|
||||
}
|
||||
::v-deep .el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
::v-deep .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
</style>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,360 @@
|
|||
<template>
|
||||
<div class="table-question-form">
|
||||
<div style="display: flex;justify-content: space-between;">
|
||||
<h3 v-if="qsForm.LesionName" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ qsForm.LesionName }}
|
||||
</h3>
|
||||
<!-- 关闭 -->
|
||||
<div>
|
||||
<i class="el-icon-circle-close" style="font-size: 25px;cursor: pointer;" @click="close" />
|
||||
</div>
|
||||
</div>
|
||||
<el-form-item
|
||||
:label="$t('trials:reading:title:lesionType')"
|
||||
prop="LesionType"
|
||||
:rules="[
|
||||
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['blur']},
|
||||
]"
|
||||
>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-model="qsForm.LesionType"
|
||||
filterable
|
||||
:disabled="!isCurrentTask || readingTaskState>=2 || !isBaseLineTask"
|
||||
@change="((val)=>{lesionTypeChange(val)})"
|
||||
>
|
||||
|
||||
<el-option
|
||||
v-for="item of $d.LesionType"
|
||||
v-show="!(isBaseLineTask && item.value === 2)"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 靶病灶、非靶病灶的器官为肝脏/Liver时,需要选择典型肝内病灶。该值默认为否;如果选择是,对于靶病灶需要提示“按照《独立影像评估章程》的相关规则,对于典型肝内靶病灶请测量肿瘤活性部分最长径。”,提示方式为在“长径”属性上,显示浮框或者增加!
|
||||
-->
|
||||
<el-form-item
|
||||
v-for="qs in questions"
|
||||
v-show="qs.ShowQuestion!==2"
|
||||
:key="qs.Id"
|
||||
:label="`${qs.QuestionName}`"
|
||||
:prop="qs.Id"
|
||||
:title="(qs.QuestionMark === 0 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1) && questionForm.IntrahepaticLesion) ? $t('trials:mRecist:warnning:msg1') : ''"
|
||||
:rules="[
|
||||
{ required: (qs.IsRequired === 0 || (qs.IsRequired ===1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10) || (qs.QuestionMark === 21 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2)) || (qs.QuestionMark === 0 && (questionForm.LesionOrgan === '肝脏' || questionForm.LesionOrgan === 'Liver') && (lesionType === 0 || lesionType === 1 || lesionType === 2))) && qs.Type!=='group' && qs.Type!=='summary',
|
||||
message:['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
|
||||
]"
|
||||
>
|
||||
<!-- 输入框 -->
|
||||
<template v-if="qs.Type==='input' || qs.Type==='number'">
|
||||
|
||||
<el-input
|
||||
v-if="qs.Type==='input' || qs.Type==='number'"
|
||||
v-model="qsForm[qs.Id]"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answer.SplitOrMergeLesionName))"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
>
|
||||
<template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(qs.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
</template>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-if="qs.Type==='textarea'"
|
||||
v-model="qsForm[qs.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-if="qs.Type==='select'"
|
||||
v-model="qsForm[qs.Id]"
|
||||
filterable
|
||||
:placeholder="qs.QuestionMark === 8 ? $t('common:placeholder:selectorsearch') : qs.QuestionMark === 2 ? '' : $t('common:placeholder:select')"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False'|| !!answer.SplitOrMergeLesionName)) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answer.SplitOrMergeLesionName))"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
>
|
||||
<template v-if="qs.QuestionMark === 8" #prefix>
|
||||
<span style="padding-left: 5px;">
|
||||
<i class="el-icon-search" />
|
||||
</span>
|
||||
</template>
|
||||
<template v-if="qs.TableQuestionType === 1">
|
||||
<el-option
|
||||
v-for="item in organList"
|
||||
:key="item.Id"
|
||||
:label="item[qs.DataTableColumn]"
|
||||
:value="item[qs.DataTableColumn]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && isBaseLineTask">
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
v-show="(lesionType === 0 && item.value ===0) || (lesionType === 1 && (item.value ===0))"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark === 7 && !isBaseLineTask">
|
||||
<el-option-group
|
||||
:label="!isNaN(parseFloat(answer.LastTaskState)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(qs.DictionaryCode,parseFloat(answer.LastTaskState))}` : ''"
|
||||
>
|
||||
<!-- 首次分裂的病灶只能选择存在 -->
|
||||
<template v-if="answer.IsFristAdd=== 'True' && answer.SplitOrMergeType === '0'">
|
||||
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
v-show="item.value === 0"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<!-- 首次添加的新病灶不能为无法评估和消失 -->
|
||||
<template v-else-if="isCurrentTaskAdd=== 'True' && lesionType === 2">
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
v-show="item.value === 0 || item.value === 1"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="item of filterState($d[qs.DictionaryCode])"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
</el-option-group>
|
||||
</template>
|
||||
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
|
||||
<el-option
|
||||
v-for="item of $d[qs.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in qs.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-if="qs.Type==='radio'"
|
||||
v-model="qsForm[qs.id]"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
||||
>
|
||||
<el-radio
|
||||
v-for="val in qs.options.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'TableQuestionFormItem',
|
||||
props: {
|
||||
tableInfo: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
answer: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
organs: {
|
||||
type: Array,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
isBaseLineTask: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isCurrentTask: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isCurrentTaskAdd: null,
|
||||
lesionType: null,
|
||||
questions: [],
|
||||
organList: [],
|
||||
qsForm: {}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
questionForm: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
if (v.MeasureData) {
|
||||
const { markTool } = v.MeasureData
|
||||
if (markTool === 'Bidirectional') {
|
||||
this.getOrganList(1)
|
||||
} else if (markTool === 'Length') {
|
||||
this.getOrganList(0)
|
||||
} else {
|
||||
this.getOrganList()
|
||||
}
|
||||
} else {
|
||||
this.getOrganList()
|
||||
}
|
||||
for (const key in v) {
|
||||
this.$set(this.qsForm, key, v[key])
|
||||
}
|
||||
this.isCurrentTaskAdd = v.IsCurrentTaskAdd
|
||||
}
|
||||
},
|
||||
tableInfo: {
|
||||
deep: true,
|
||||
immediate: true,
|
||||
handler(v) {
|
||||
if (v) {
|
||||
this.lesionType = v.LesionType
|
||||
this.questions = v.TableQuestions.Questions
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
lesionTypeChange(v) {
|
||||
this.$emit('lesionTypeChange', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, newLesionType: v })
|
||||
},
|
||||
formItemChange(v, qs) {
|
||||
const updateArr = []
|
||||
if (qs.QuestionMark === 8 && qs.RelationQuestions.length > 0) {
|
||||
// 当选择部位时,联动器官、位置、是否淋巴结问题答案
|
||||
const index = this.organList.findIndex(item => item[qs.DataTableColumn] === v)
|
||||
if (index > -1) {
|
||||
const selected = this.organList[index]
|
||||
qs.RelationQuestions.map(q => {
|
||||
const val = selected[q.DataTableColumn]
|
||||
updateArr.push({ questionId: q.Id, val: val, questionMark: q.QuestionMark })
|
||||
})
|
||||
updateArr.push({ questionId: 'OrganInfoId', val: selected.OrganInfoId })
|
||||
updateArr.push({ questionId: 'IsCanEditPosition', val: selected.IsCanEditPosition })
|
||||
} else {
|
||||
qs.RelationQuestions.map(q => {
|
||||
updateArr.push({ questionId: q.Id, val: '', questionMark: q.QuestionMark })
|
||||
})
|
||||
}
|
||||
}
|
||||
this.$emit('update', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex, questionMark: qs.QuestionMark, questionId: qs.Id, val: v, updateArr })
|
||||
},
|
||||
getOrganList(isLymphNodes = null) {
|
||||
const idx = this.organs.findIndex(i => i.LesionType === this.questionForm.LesionType)
|
||||
if (idx > -1) {
|
||||
const arr = this.organs[idx].OrganList
|
||||
|
||||
if (!isNaN(parseInt(isLymphNodes))) {
|
||||
this.organList = arr.filter((item) => item.IsLymphNodes === parseInt(isLymphNodes))
|
||||
} else {
|
||||
this.organList = arr
|
||||
}
|
||||
}
|
||||
},
|
||||
filterState(arr) {
|
||||
if (!this.isBaseLineTask) {
|
||||
const isLymphLesion = this.questionForm.IsLymphNodes
|
||||
const lesionLength = this.questionForm.LesionLength
|
||||
const lesionShort = this.questionForm.LesionShort
|
||||
const bLesionL = !isNaN(parseFloat(this.questionForm.BaseLineMajorAxis)) ? parseFloat(this.questionForm.BaseLineMajorAxis) : 0
|
||||
const bLesionS = !isNaN(parseFloat(this.questionForm.BaseLineShortAxis)) ? parseFloat(this.questionForm.BaseLineShortAxis) : 0
|
||||
if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort < bLesionS) {
|
||||
arr = arr.filter(i => i.value !== 1)
|
||||
} else if (this.lesionType === 1 && isLymphLesion === 1 && this.questionForm.MeasureData && this.questionForm.MeasureData.markTool === 'Bidirectional' && lesionShort >= 10 && lesionShort > bLesionS) {
|
||||
arr = arr.filter(i => i.value === 0 || i.value === 1)
|
||||
} else if (this.lesionType === 1 && isLymphLesion === 0 && this.questionForm.MeasureData && (this.questionForm.MeasureData.markTool === 'Length' || this.questionForm.MeasureData.markTool === 'Bidirectional') && lesionLength < bLesionL) {
|
||||
arr = arr.filter(i => i.value !== 1)
|
||||
}
|
||||
return arr
|
||||
} else {
|
||||
return arr
|
||||
}
|
||||
},
|
||||
close() {
|
||||
this.$emit('close', { tableId: this.tableInfo.Id, rowIndex: this.answer.RowIndex })
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.table-question-form{
|
||||
::v-deep .el-form-item__label{
|
||||
color: #c3c3c3;
|
||||
}
|
||||
::v-deep .el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
::v-deep .el-form-item{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
::v-deep .el-form-item__content{
|
||||
flex: 1;
|
||||
}
|
||||
::v-deep .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
::v-deep .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
::v-deep .el-button--mini, .el-button--mini.is-round {
|
||||
padding: 7px 10px;
|
||||
}
|
||||
.el-form-item__content
|
||||
.el-select{
|
||||
width: 100%;
|
||||
}
|
||||
.input-width1{
|
||||
width: calc(100% - 60px)!important;
|
||||
}
|
||||
.input-width2{
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
|
@ -8,25 +8,33 @@ const config = {
|
|||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -38,25 +46,33 @@ const config = {
|
|||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -68,25 +84,33 @@ const config = {
|
|||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -98,25 +122,33 @@ const config = {
|
|||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "长短径测量工具",
|
||||
"icon": "bidirection",
|
||||
"toolName": "Bidirectional",
|
||||
"i18nKey": "trials:reading:button:bidirectional"
|
||||
"i18nKey": "trials:reading:button:bidirectional",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -128,13 +160,17 @@ const config = {
|
|||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -146,19 +182,25 @@ const config = {
|
|||
"name": "直径测量工具",
|
||||
"icon": "length",
|
||||
"toolName": "Length",
|
||||
"i18nKey": "trials:reading:button:length"
|
||||
"i18nKey": "trials:reading:button:length",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "矩形工具",
|
||||
"icon": "rectangle",
|
||||
"toolName": "RectangleRoi",
|
||||
"i18nKey": "trials:reading:button:rectangle"
|
||||
"i18nKey": "trials:reading:button:rectangle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
},
|
||||
{
|
||||
"name": "箭头工具",
|
||||
"icon": "arrow",
|
||||
"toolName": "ArrowAnnotate",
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate"
|
||||
"i18nKey": "trials:reading:button:arrowAnnotate",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -180,7 +222,9 @@ const config = {
|
|||
"name": "圆形测量",
|
||||
"icon": "oval",
|
||||
"toolName": "Probe",
|
||||
"i18nKey": "trials:reading:button:circle"
|
||||
"i18nKey": "trials:reading:button:circle",
|
||||
"isDisabled": false,
|
||||
"disabledReason": ''
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue