wangxiaoshuang 2025-06-12 16:18:49 +08:00
commit 818a8add3d
7 changed files with 844 additions and 187 deletions

View File

@ -50,6 +50,8 @@ const getters = {
IsFirstSysDocNeedSign: state => state.user.IsFirstSysDocNeedSign, IsFirstSysDocNeedSign: state => state.user.IsFirstSysDocNeedSign,
TrialStatusStr: state => state.user.TrialStatusStr, TrialStatusStr: state => state.user.TrialStatusStr,
lastViewportTaskId: state => state.noneDicomReview.lastViewportTaskId, lastViewportTaskId: state => state.noneDicomReview.lastViewportTaskId,
currentTaskState: state => state.noneDicomReview.currentTaskState currentTaskState: state => state.noneDicomReview.currentTaskState,
operateInfo: state => state.dicom3d.operateInfo,
deleteAnnotationIds: state => state.dicom3d.deleteAnnotationIds
} }
export default getters export default getters

View File

@ -13,6 +13,7 @@ import financials from './modules/financials'
import reading from './modules/reading' import reading from './modules/reading'
import lang from './modules/lang' import lang from './modules/lang'
import noneDicomReview from './modules/noneDicomReview' import noneDicomReview from './modules/noneDicomReview'
import dicom3d from './modules/dicom3d'
Vue.use(Vuex) Vue.use(Vuex)
const store = new Vuex.Store({ const store = new Vuex.Store({
@ -28,7 +29,8 @@ const store = new Vuex.Store({
financials, financials,
reading, reading,
lang, lang,
noneDicomReview noneDicomReview,
dicom3d
}, },
getters getters
}) })

View File

@ -0,0 +1,28 @@
const getDefaultState = () => {
return {
operateInfo: {},
deleteAnnotationIds: []
}
}
const state = getDefaultState
const mutations = {
}
const actions = {
setOperateInfo({ state }, obj) {
state.operateInfo = Object.assign({}, obj)
},
setDeleteAnnotationIds({ state }, arr) {
state.deleteAnnotationIds = Object.assign({}, obj)
},
}
export default {
namespaced: true,
state,
mutations,
actions
}

View File

@ -438,6 +438,7 @@
@resetAnnotations="resetAnnotations" @resetAnnotations="resetAnnotations"
@setReadingTaskState="setReadingTaskState" @setReadingTaskState="setReadingTaskState"
@viewCustomAnnotationSeries="viewCustomAnnotationSeries" @viewCustomAnnotationSeries="viewCustomAnnotationSeries"
@getCustomScreenshots="getCustomScreenshots"
@setReadingToolActive="setReadingToolActive" @setReadingToolActive="setReadingToolActive"
@setReadingToolPassive="setReadingToolPassive" @setReadingToolPassive="setReadingToolPassive"
/> />
@ -562,6 +563,8 @@ import * as cornerstoneTools from '@cornerstonejs/tools'
import initLibraries from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/initLibraries' import initLibraries from '@/views/trials/trials-panel/reading/dicoms/components/Fusion/js/initLibraries'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import { getTools, getCustomizeStandardsTools, config } from './toolConfig' import { getTools, getCustomizeStandardsTools, config } from './toolConfig'
import { mapGetters } from 'vuex'
import store from '@/store'
import StudyList from './StudyList' import StudyList from './StudyList'
import Viewport from './Viewport' import Viewport from './Viewport'
import PetCtViewport from './PetCtViewport' import PetCtViewport from './PetCtViewport'
@ -751,7 +754,7 @@ export default {
}, },
viewportKey() { viewportKey() {
return this.isFusion ? 'viewport-fusion' : 'viewport' return this.isFusion ? 'viewport-fusion' : 'viewport'
} },
}, },
watch: { watch: {
activeTaskId: { activeTaskId: {
@ -1450,15 +1453,19 @@ export default {
annotation.numberOfFrames = isNaN(parseInt(params.frame)) ? null : parseInt(params.frame) annotation.numberOfFrames = isNaN(parseInt(params.frame)) ? null : parseInt(params.frame)
annotation.markTool = annotation.metadata.toolName annotation.markTool = annotation.metadata.toolName
this.markedSeriesIds.push(series.Id) this.markedSeriesIds.push(series.Id)
const markName = await this.customPrompt() const operateStateEnum = this.$refs[`ecrf_${this.taskInfo.VisitTaskId}`][0].operateStateEnum
const markName = await this.customPrompt(!this.isNumber(operateStateEnum))
if (markName) { if (markName) {
annotation.data.label = markName annotation.data.label = markName
if (annotation.metadata.toolName === 'ArrowAnnotate') { if (annotation.metadata.toolName === 'ArrowAnnotate') {
annotation.data.text = markName annotation.data.text = markName
} }
this.saveCustomAnnotation(annotation) if (this.isNumber(operateStateEnum)) {
this.$refs[`ecrf_${series.TaskInfo.VisitTaskId}`][0].bindAnnotationToQuestion(annotation) this.$refs[`ecrf_${series.TaskInfo.VisitTaskId}`][0].bindAnnotationToQuestion(annotation)
} else {
this.saveCustomAnnotation(annotation)
}
} }
} }
@ -1500,8 +1507,13 @@ export default {
if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return if (annotation.metadata.toolName === 'PlanarFreehandROI' && !annotation.data.contour.closed) return
const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series const series = this.$refs[`${this.viewportKey}-${this.activeViewportIndex}`][0].series
if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) { if (series && series.TaskInfo.VisitTaskId && series.TaskInfo.VisitTaskId === this.taskInfo.VisitTaskId) {
this.saveCustomAnnotation(annotation) const operateStateEnum = this.$refs[`ecrf_${this.taskInfo.VisitTaskId}`][0].operateStateEnum
this.$refs[`ecrf_${series.TaskInfo.VisitTaskId}`][0].updateAnnotationToQuestion(annotation) const isBound = this.$refs[`ecrf_${annotation.visitTaskId}`][0].verifyAnnotationIsBound(annotation)
if (isBound || this.isNumber(operateStateEnum)) {
this.$refs[`ecrf_${series.TaskInfo.VisitTaskId}`][0].updateAnnotationToQuestion(annotation)
} else {
this.saveCustomAnnotation(annotation)
}
} }
this.setToolsPassive() this.setToolsPassive()
}, },
@ -1521,7 +1533,7 @@ export default {
} }
if (annotation.visitTaskId === this.taskInfo.VisitTaskId) { if (annotation.visitTaskId === this.taskInfo.VisitTaskId) {
const isBound = this.$refs[`ecrf_${annotation.visitTaskId}`][0].verifyAnnotationIsBound(annotation) const isBound = this.$refs[`ecrf_${annotation.visitTaskId}`][0].verifyAnnotationIsBound(annotation)
if (isBound) { if (isBound && this.activeTool === 'Eraser') {
this.$alert('该标记已与问题进行绑定,不允许删除!') this.$alert('该标记已与问题进行绑定,不允许删除!')
const errorMsg = { message: 'annotation Not allowed to operate' } const errorMsg = { message: 'annotation Not allowed to operate' }
throw errorMsg throw errorMsg
@ -2589,6 +2601,23 @@ export default {
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex) this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
} }
}, },
async getCustomScreenshots(obj, callback) {
const i = this.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
if (i === -1) return
const studyList = this.visitTaskList[i].StudyList
const series = this.getMarkedSeries(studyList, obj.annotation)
if (series) {
this.$refs[`${this.viewportKey}-${this.cells.length - 1}`][0].setSeriesInfo(series, true)
this.activeViewportIndex = i
this.$refs[series.TaskInfo.VisitTaskId][0].setSeriesActive(series.StudyIndex, series.SeriesIndex)
const divForDownloadViewport = document.querySelector(
`div[data-viewport-uid="${this.viewportKey}-${this.activeViewportIndex}"]`
)
const canvas = await html2canvas(divForDownloadViewport)
const base64Str = canvas.toDataURL('image/png', 1)
callback(base64Str)
}
},
async getScreenshots(measureData, callback) { async getScreenshots(measureData, callback) {
if (measureData) { if (measureData) {
await this.imageLocation(measureData) await this.imageLocation(measureData)
@ -2787,12 +2816,13 @@ export default {
return params return params
}, },
// //
async customPrompt() { async customPrompt(isShowCancelButton = true) {
try { try {
const that = this const that = this
// //
const { value } = await this.$prompt(this.$t('trials:noneDicom:message:msg1'), '', { const { value } = await this.$prompt(this.$t('trials:noneDicom:message:msg1'), '', {
showClose: false, showClose: false,
showCancelButton: isShowCancelButton,
beforeClose: (action, instance, done) => { beforeClose: (action, instance, done) => {
if (action === 'confirm') { if (action === 'confirm') {
const value = instance.inputValue const value = instance.inputValue
@ -2813,6 +2843,9 @@ export default {
return null return null
} }
}, },
isNumber(value) {
return typeof value === 'number' && value !== null && !isNaN(value)
},
showPanel(e, toolName) { showPanel(e, toolName) {
if (toolName === 'layout' && this.isFusion) return false if (toolName === 'layout' && this.isFusion) return false
e.currentTarget.firstChild.lastChild.style.display = 'block' e.currentTarget.firstChild.lastChild.style.display = 'block'

View File

@ -54,12 +54,64 @@
<el-button type="text" size="mini" @click="openAddTableCol(question, scope.$index)"> <el-button type="text" size="mini" @click="openAddTableCol(question, scope.$index)">
{{$t('common:button:edit')}} {{$t('common:button:edit')}}
</el-button> </el-button>
<el-button type="text" size="mini" v-if="scope.row.IsCurrentTaskAdd === 'True' || !question.IsCopyLesions || isBaseline" @click="deleteTableCol(question, scope.$index)"> <el-button type="text" size="mini" :disabled="addOrEdit.visible" v-if="scope.row.IsCurrentTaskAdd === 'True' || !question.IsCopyLesions || isBaseline" @click="deleteTableCol(question, scope.$index)">
{{$t('common:button:delete')}} {{$t('common:button:delete')}}
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<el-dialog
v-if="addOrEdit.visible"
v-dialogDrag
:title="addOrEdit.title"
:visible.sync="addOrEdit.visible"
:close-on-click-modal="false"
:close-on-press-escape="false"
width="400px"
:modal="false"
:before-close="beforeClose"
>
<div>
<el-form
ref="tableQsForm"
:model="QuestionsForm"
v-loading="loading"
size="small"
>
<QuestionTableFormItem
v-for="(item) in QuestionsList"
:key="item.Id"
:question="item"
:parentQsId="parentQsId"
:isBaseline="isBaseline"
:reading-task-state="readingTaskState"
:question-form="QuestionsForm"
:visit-task-id="visitTaskId"
:criterion-id="criterionId"
:type="addOrEdit.type"
:calculationList="calculationList"
:questionsMarkStatus="questionsMarkStatus"
@formItemTableNumberChange="formItemTableNumberChange"
@resetFormItemData="resetTableFormItemData"
@setFormItemData="setFormTableItemData"
@operateImageMarker="operateImageMarker"
@save="save"
/>
</el-form>
</div>
<div slot="footer" >
<el-button
size="small"
@click="handleCancel"
>
{{ $t('common:button:cancel') }}
</el-button>
<!-- 保存 -->
<el-button size="small" class="my_upload_btn" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</div>
</el-dialog>
</div> </div>
<template v-else> <template v-else>
<el-form-item <el-form-item
@ -234,7 +286,7 @@
@change="(val) => { formItemNumberChange(val, question) }" @change="(val) => { formItemNumberChange(val, question) }"
@blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? ()=>{} : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question) " @blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? ()=>{} : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question) "
v-model="questionForm[question.Id]" v-model="questionForm[question.Id]"
:disabled="(questionsMarkStatus[question.Id].isMarked && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1" :disabled="(questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1"
style="width: 150px;" style="width: 150px;"
> >
<template v-if="question.Unit !== 0" slot="append"> <template v-if="question.Unit !== 0" slot="append">
@ -243,7 +295,7 @@
</el-input> </el-input>
<!-- 测量 --> <!-- 测量 -->
<el-button <el-button
v-if="readingTaskState < 2 && (!questionsMarkStatus[question.Id].isMarked)" v-if="readingTaskState < 2 && (!questionsMarkStatus[question.Id] || (questionsMarkStatus[question.Id] && !questionsMarkStatus[question.Id].isMarked))"
size="mini" size="mini"
type="text" type="text"
@click="operateImageMarker({operateStateEnum: 1, question})" @click="operateImageMarker({operateStateEnum: 1, question})"
@ -252,7 +304,7 @@
</el-button> </el-button>
<!-- 绑定 --> <!-- 绑定 -->
<el-button <el-button
v-if="readingTaskState < 2 && (!questionsMarkStatus[question.Id].isMarked)" v-if="readingTaskState < 2 && (!questionsMarkStatus[question.Id] || (questionsMarkStatus[question.Id] && !questionsMarkStatus[question.Id].isMarked))"
size="mini" size="mini"
type="text" type="text"
@click="operateImageMarker({operateStateEnum: 0, question})" @click="operateImageMarker({operateStateEnum: 0, question})"
@ -261,7 +313,7 @@
</el-button> </el-button>
<!-- 查看 --> <!-- 查看 -->
<el-button <el-button
v-if="questionsMarkStatus[question.Id].isMarked" v-if="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked"
size="mini" size="mini"
type="text" type="text"
@click="operateImageMarker({operateStateEnum: 2, question})" @click="operateImageMarker({operateStateEnum: 2, question})"
@ -270,7 +322,7 @@
</el-button> </el-button>
<!-- 更改 --> <!-- 更改 -->
<el-button <el-button
v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id].isMarked)" v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked)"
size="mini" size="mini"
type="text" type="text"
@click="operateImageMarker({operateStateEnum: 3, question})" @click="operateImageMarker({operateStateEnum: 3, question})"
@ -279,7 +331,7 @@
</el-button> </el-button>
<!-- 移除 --> <!-- 移除 -->
<el-button <el-button
v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id].isMarked)" v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked)"
size="mini" size="mini"
type="text" type="text"
@click="operateImageMarker({operateStateEnum: 4, question})" @click="operateImageMarker({operateStateEnum: 4, question})"
@ -288,12 +340,12 @@
</el-button> </el-button>
<!-- 保存 --> <!-- 保存 -->
<el-button <el-button
v-if="readingTaskState < 2 && !questionsMarkStatus[question.Id].isSaved" v-if="readingTaskState < 2 && (questionsMarkStatus[question.Id] && !questionsMarkStatus[question.Id].isSaved)"
size="mini" size="mini"
type="text" type="text"
@click="operateImageMarker({operateStateEnum: 5, question})" @click="operateImageMarker({operateStateEnum: 5, question})"
> >
<el-tooltip v-if="!questionsMarkStatus[question.Id].isSaved" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom"> <el-tooltip v-if="questionsMarkStatus[question.Id] && !questionsMarkStatus[question.Id].isSaved" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<i class="el-icon-warning" style="color:red" /> <i class="el-icon-warning" style="color:red" />
</el-tooltip> </el-tooltip>
保存 保存
@ -378,51 +430,20 @@
@resetFormItemData="resetFormItemData" @resetFormItemData="resetFormItemData"
@getQuestions="getQuestions" @getQuestions="getQuestions"
@operateImageMarker="operateImageMarker" @operateImageMarker="operateImageMarker"
@unBindAnnotationToQuestion="unBindAnnotationToQuestion"
/> />
</template> </template>
<base-model :config="addOrEdit"
<!-- <base-model :config="addOrEdit"
class="my_dialog" class="my_dialog"
:close-on-click-modal="false" :close-on-click-modal="false"
:close-on-press-escape="false"
width="400px" width="400px"
append-to-body :modal="false"
v-dialogDrag
> >
<template slot="dialog-body">
<el-form </base-model> -->
ref="tableQsForm"
:model="QuestionsForm"
v-loading="loading"
size="small"
>
<QuestionTableFormItem
v-for="(item) in QuestionsList"
:key="item.Id"
:question="item"
:isBaseline="isBaseline"
:reading-task-state="readingTaskState"
:question-form="QuestionsForm"
:visit-task-id="visitTaskId"
:criterion-id="criterionId"
:type="addOrEdit.type"
:calculationList="calculationList"
@formItemTableNumberChange="formItemTableNumberChange"
@resetFormItemData="resetTableFormItemData"
@setFormItemData="setFormTableItemData"
/>
</el-form>
</template>
<template slot="dialog-footer">
<el-button
size="small"
@click="addOrEdit.visible = false"
>
{{ $t('common:button:cancel') }}
</el-button>
<!-- 保存 -->
<el-button size="small" class="my_upload_btn" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</template>
</base-model>
<!-- 预览文件 --> <!-- 预览文件 -->
<el-dialog <el-dialog
v-if="previewVisible" v-if="previewVisible"
@ -446,10 +467,12 @@
</div> </div>
</template> </template>
<script> <script>
import { deleteReadingRowAnswer, getQuestionCalculateRelation, submitTableQuestion } from '@/api/trials' import { deleteReadingRowAnswer, getQuestionCalculateRelation, submitTableQuestion, deleteCustomTag } from '@/api/trials'
import QuestionTableFormItem from './QuestionTableFormItem' import QuestionTableFormItem from './QuestionTableFormItem'
import BaseModel from '@/components/BaseModel' import BaseModel from '@/components/BaseModel'
import PreviewFile from '@/components/PreviewFile/index' import PreviewFile from '@/components/PreviewFile/index'
import { mapGetters } from 'vuex'
import store from '@/store'
export default { export default {
name: 'QuestionFormItem', name: 'QuestionFormItem',
components: { QuestionTableFormItem, BaseModel, PreviewFile }, components: { QuestionTableFormItem, BaseModel, PreviewFile },
@ -517,9 +540,14 @@ export default {
classArr: [], classArr: [],
previewVisible: false, previewVisible: false,
currentPath: '', currentPath: '',
currentType: '' currentType: '',
markTableQuestions: [],
parentQsId: ''
} }
}, },
computed: {
...mapGetters(['operateInfo'])
},
watch: { watch: {
questionForm: { questionForm: {
deep: true, deep: true,
@ -547,8 +575,32 @@ export default {
handler(v, oldv) { handler(v, oldv) {
// console.log(v) // console.log(v)
} }
},
operateInfo: {
immediate: true,
handler(v) {
const { parentQsId, rowId } = v
if (this.question.Id !== parentQsId) return
if (this.addOrEdit.visible) {
//
this.setAnswerToQuestion(v)
} else {
//
// const { parentQsId, rowId } = v
if (!parentQsId && !rowId) return
let arr = this.questionForm[parentQsId]
if (!arr || !Array.isArray(arr)) return
let i = arr.findIndex(i=>i.RowId === rowId)
if (i === -1) return
this.openAddTableCol(this.question, i)
}
}
} }
}, },
mounted() { mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces')) var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
@ -605,25 +657,39 @@ export default {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces)) this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
this.$emit('operateImageMarker', {operateStateEnum: 6, question}) this.$emit('operateImageMarker', {operateStateEnum: 6, question})
}, },
deleteTableCol(row, index) { async deleteTableCol(row, index) {
this.$confirm(this.$t('trials:uploadNonDicoms:message:msg1')).then(() => { let loading = null
const loading = this.$loading({ fullscreen: true }) try {
var param = { let confirm = await this.$confirm(this.$t('trials:uploadNonDicoms:message:msg1'))
if (confirm !== 'confirm') return
loading = this.$loading({ fullscreen: true })
let param = {
visitTaskId: this.visitTaskId, visitTaskId: this.visitTaskId,
questionId: row.Id, questionId: row.Id,
rowId: this.questionForm[row.Id][index].RowId rowId: this.questionForm[row.Id][index].RowId
} }
deleteReadingRowAnswer(param) let res = await deleteReadingRowAnswer(param)
.then(async res => { if (res.IsSuccess) {
if (res.IsSuccess) { //
this.$message.success(this.$t('common:message:deletedSuccessfully')) // let deleteAnnotationIds = []
this.$emit('getQuestions') // let arr = this.questionMarkInfoList.filter(i=>i.RowId === this.questionForm[row.Id][index].RowId)
} // for(let i = 0; i < arr.length; i++) {
loading.close() // if (arr[i].Id && arr[i].MeasureData) {
}).catch(() => { // let measureData = arr[i].MeasureData
loading.close() // deleteAnnotationIds.push(measureData.annotationUID)
}) // await deleteCustomTag(arr[i].Id)
}) // }
// }
// store.dispatch('dicom3d/setDeleteAnnotationIds', deleteAnnotationIds)
//
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$emit('getQuestions')
}
loading.close()
} catch(e) {
loading ? loading.close() : ''
console.log(e)
}
}, },
setFormTableItemData(obj) { setFormTableItemData(obj) {
@ -679,12 +745,27 @@ export default {
getQuestions() { getQuestions() {
this.$emit('getQuestions') this.$emit('getQuestions')
}, },
handleSave() { async handleSave() {
this.$refs.tableQsForm.validate(valid => { let loading = null
try {
let valid = await this.$refs.tableQsForm.validate()
if (!valid) return if (!valid) return
const loading = this.$loading({ fullscreen: true }) //
var answers = [] let isExistUnSaved = false
var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/) for(let i = 0; i < this.markTableQuestions.length; i++) {
let keyId = this.QuestionsForm.RowId ? `${this.QuestionsForm.RowId}_${this.markTableQuestions[i]}` : this.markTableQuestions[i]
if (this.questionsMarkStatus[keyId] && !this.questionsMarkStatus[keyId].isSaved) {
isExistUnSaved = true
break
}
}
if (isExistUnSaved) {
this.$alert('存在标记信息未保存!')
return
}
loading = this.$loading({ fullscreen: true })
let answers = []
let reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
for (const k in this.QuestionsForm) { for (const k in this.QuestionsForm) {
if (reg.test(k)) { if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) { if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
@ -692,8 +773,9 @@ export default {
} }
} }
} }
let params = null
if (this.addOrEdit.type === 'edit') { if (this.addOrEdit.type === 'edit') {
var params = { params = {
questionId: this.question.Id, questionId: this.question.Id,
RowIndex: parseInt(this.QuestionsForm.RowIndex), RowIndex: parseInt(this.QuestionsForm.RowIndex),
RowId: this.QuestionsForm.RowId, RowId: this.QuestionsForm.RowId,
@ -702,22 +784,31 @@ export default {
answerList: answers, answerList: answers,
} }
} else { } else {
var params = { params = {
questionId: this.question.Id, questionId: this.question.Id,
RowIndex: this.questionForm[this.question.Id].length + 1, RowIndex: this.questionForm[this.question.Id].length + 1,
RowId: this.QuestionsForm.RowId ? this.QuestionsForm.RowId : '',
visitTaskId: this.visitTaskId, visitTaskId: this.visitTaskId,
trialId: this.$route.query.trialId, trialId: this.$route.query.trialId,
answerList: answers, answerList: answers
} }
this.QuestionsForm.RowIndex = this.questionForm[this.question.Id].length + 1 this.QuestionsForm.RowIndex = this.questionForm[this.question.Id].length + 1
} }
submitTableQuestion(params).then(async res => { let res = await submitTableQuestion(params)
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success(this.$t('common:message:savedSuccessfully'))
this.QuestionsForm.RowId = res.Result.RowId this.QuestionsForm.RowId = res.Result.RowId
// this.$emit('getQuestions')
this.save() this.save()
loading.close() }
}).catch(() => { loading.close() }) loading.close()
}) } catch (e) {
loading ? loading.close() : ''
console.log(e)
}
},
saveRowInfo() {
}, },
renderHeader(h, obj) { renderHeader(h, obj) {
let span = document.createElement('span') let span = document.createElement('span')
@ -749,6 +840,36 @@ export default {
this.addOrEdit.visible = false this.addOrEdit.visible = false
}) })
}, },
async handleCancel() {
//
let isExistUnSaved = false
for(let i = 0; i < this.markTableQuestions.length; i++) {
let keyId = this.QuestionsForm.RowId ? `${this.QuestionsForm.RowId}_${this.markTableQuestions[i]}` : this.markTableQuestions[i]
if (this.questionsMarkStatus[keyId] && !this.questionsMarkStatus[keyId].isSaved) {
isExistUnSaved = true
break
}
}
if (isExistUnSaved) {
// this.$alert('')
const confirm = await this.$confirm('标记未保存是否确认关闭?', {
type: 'warning',
distinguishCancelAndClose: true
})
if (confirm !== 'confirm') return
//
let obj = {}
if (!this.QuestionsForm.RowId) {
obj.markTableQuestions = this.markTableQuestions
obj.questionId = this.question.Id
this.$emit('unBindAnnotationToQuestion', obj)
}
this.addOrEdit.visible = false
} else {
this.addOrEdit.visible = false
}
},
logic(rules, num = 0) { logic(rules, num = 0) {
try { try {
if (rules.CalculateQuestionList.length === 0) { if (rules.CalculateQuestionList.length === 0) {
@ -958,18 +1079,24 @@ export default {
}); });
}, },
openAddTableCol(row, index) { openAddTableCol(row, index) {
if (this.addOrEdit.visible) return
this.parentQsId = row.Id
this.addOrEdit.visible = true this.addOrEdit.visible = true
this.addOrEdit.title = row.QuestionName + this.$t('trials:readingUnit:qsList:title:tableQs') this.addOrEdit.title = row.QuestionName + this.$t('trials:readingUnit:qsList:title:tableQs')
this.QuestionsList = row.TableQuestions.Questions this.QuestionsList = row.TableQuestions.Questions
this.markTableQuestions = []
row.TableQuestions.Questions.map(v=>{ row.TableQuestions.Questions.map(v=>{
if (v.Type === 'class') { if (v.Type === 'class') {
this.classArr.push({triggerId: v.ClassifyTableQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType}) this.classArr.push({triggerId: v.ClassifyTableQuestionId, classId: v.Id, classifyAlgorithms: v.ClassifyAlgorithms, classifyType: v.ClassifyType})
} }
if (v.ImageMarkEnum === 1 || v.ImageMarkEnum == 2) {
this.markTableQuestions.push(v.Id)
}
}) })
this.AnswersList = row.TableQuestions.Answers this.AnswersList = row.TableQuestions.Answers
if (!index && index !== 0) { if (!index && index !== 0) {
this.addOrEdit.type = 'add' this.addOrEdit.type = 'add'
this.QuestionsForm = {} this.QuestionsForm = {RowIndex: this.questionForm[this.question.Id].length + 1}
} else { } else {
this.addOrEdit.type = 'edit' this.addOrEdit.type = 'edit'
this.QuestionsForm = Object.assign({}, this.questionForm[row.Id][index]) this.QuestionsForm = Object.assign({}, this.questionForm[row.Id][index])
@ -1011,9 +1138,132 @@ export default {
setFormItemData(obj) { setFormItemData(obj) {
this.$emit('setFormItemData', obj) this.$emit('setFormItemData', obj)
}, },
operateImageMarker(obj) { // async operateImageMarker(obj) {
// if (obj.question.IsTableQuestion && obj.operateStateEnum === 4) {
// //
// this.$set(this.QuestionsForm, obj.question.Id, null)
// } else if (obj.question.IsTableQuestion && obj.operateStateEnum === 7 && obj.rowId) {
// this.$set(this.QuestionsForm, 'RowId', obj.rowId)
// }
// this.$emit('operateImageMarker', obj)
// },
async operateImageMarker(obj) {
// if (obj.question.IsTableQuestion && this.question.Id !== obj.question.ParentQsId) return
if (obj.question.IsTableQuestion && obj.operateStateEnum === 4) {
//
this.$set(this.QuestionsForm, obj.question.Id, null)
} else if (obj.question.IsTableQuestion && obj.operateStateEnum === 7 && this.question.Id === obj.question.ParentQsId) {
if (!this.QuestionsForm.RowId) {
//
let loading = null
try {
loading = this.$loading({ fullscreen: true })
let answers = []
let reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
for (const k in this.QuestionsForm) {
if (reg.test(k)) {
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
answers.push({ tableQuestionId: k, answer: this.QuestionsForm[k] })
}
}
}
let params = {
questionId: this.question.Id,
RowIndex: this.questionForm[this.question.Id].length + 1,
RowId: this.QuestionsForm.RowId ? this.QuestionsForm.RowId : '',
visitTaskId: this.visitTaskId,
trialId: this.$route.query.trialId,
answerList: answers
}
let res = await submitTableQuestion(params)
if (res.IsSuccess) {
this.QuestionsForm.RowId = res.Result.RowId
obj.rowId = res.Result.RowId
this.AnswersList.push(this.QuestionsForm)
this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question})
this.formItemNumberChange(this.question.Id, true)
}
loading.close()
} catch(e) {
console.log(e)
loading.close()
}
} else {
let i = this.AnswersList.findIndex(i=>i.RowId === this.QuestionsForm.RowId)
this.AnswersList[i][obj.question.Id] = this.QuestionsForm[obj.question.Id]
this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question})
this.formItemNumberChange(this.question.Id, true)
}
}
this.$emit('operateImageMarker', obj) this.$emit('operateImageMarker', obj)
}, },
unBindAnnotationToQuestion(obj) {
this.$emit('unBindAnnotationToQuestion', obj)
},
setAnswerToQuestion(obj) {
console.log('setAnswerToQuestion')
let val = null
const {questionId, annotation} = obj
if (!questionId || !annotation) return
const referencedImageId = annotation.metadata.referencedImageId
if (annotation.metadata.toolName === 'Length') {
let length = annotation.data.cachedStats[`imageId:${referencedImageId}`].length
val = length ? parseFloat(length).toFixed(this.digitPlaces) : length
} else if (annotation.metadata.toolName === 'Bidirectional') {
if (obj.imageToolAttribute === 'length') {
let length = annotation.data.cachedStats[`imageId:${referencedImageId}`].length
val = length ? parseFloat(length).toFixed(this.digitPlaces) : length
this.$set(this.QuestionsForm, questionId, length)
} else if (obj.imageToolAttribute === 'width') {
let short = annotation.data.cachedStats[`imageId:${referencedImageId}`].width
val = short ? parseFloat(short).toFixed(this.digitPlaces) : short
}
}
this.$set(this.QuestionsForm, questionId, val)
// this.AnswersList.push(this.QuestionsForm)
// this.$emit('setFormItemData', {key: this.question.Id, val: this.AnswersList, question: this.question})
// this.formItemNumberChange(this.question.Id, true)
},
async beforeClose(done) {
try {
//
let isExistUnSaved = false
for(let i = 0; i < this.markTableQuestions.length; i++) {
let keyId = this.QuestionsForm.RowId ? `${this.QuestionsForm.RowId}_${this.markTableQuestions[i]}` : this.markTableQuestions[i]
if (this.questionsMarkStatus[keyId] && !this.questionsMarkStatus[keyId].isSaved) {
isExistUnSaved = true
break
}
}
if (isExistUnSaved) {
const confirm = await this.$confirm('标记未保存是否确认关闭?', {
type: 'warning',
distinguishCancelAndClose: true
})
if (confirm !== 'confirm') return
//
let obj = {}
if (!this.QuestionsForm.RowId) {
obj.markTableQuestions = this.markTableQuestions
obj.questionId = this.question.Id
this.$emit('unBindAnnotationToQuestion', obj)
}
done()
// this.$alert('')
} else {
done()
}
} catch (e) {
}
},
async uploadScreenshot(param) { async uploadScreenshot(param) {
if (!this.visitTaskId) return if (!this.visitTaskId) return
const loading = this.$loading({ const loading = this.$loading({
@ -1095,19 +1345,20 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.my_dialog{ .criterion-form-item {
.criterion-form-item{ // 穿
width: 100%; ::v-deep .el-dialog{
::v-deep .el-form-item__content{ pointer-events:auto;
width: auto; margin-right: 15px !important;
} margin-top: 30vh !important;
//::v-deep .el-input-goup__append{
// background-color: transparent;
// color: #ddd;
// border: 1px solid #5e5e5e;
//}
}
} }
::v-deep .el-dialog__wrapper{
pointer-events:none;
}
// .custom-dialog .el-dialog__wrapper {
// pointer-events:none;
// }
::v-deep .el-form-item__label{ ::v-deep .el-form-item__label{
color: #c3c3c3; color: #c3c3c3;
} }
@ -1124,6 +1375,7 @@ export default {
color: #ddd; color: #ddd;
border: 1px solid #5e5e5e; border: 1px solid #5e5e5e;
} }
}
.criterion-form-item{ .criterion-form-item{
::v-deep .criterion-form-item .el-form-item{ ::v-deep .criterion-form-item .el-form-item{
display: block; display: block;
@ -1142,30 +1394,31 @@ export default {
.el-input{ .el-input{
width:100%; width:100%;
} }
.mb{ .mb{
margin-bottom: 0px; margin-bottom: 0px;
} }
.disabled{ .disabled{
::v-deep .el-upload--picture-card { ::v-deep .el-upload--picture-card {
display: none;
}
}
.uploadWrapper{
display: flex;
flex-direction: column;
align-items: flex-start;
}
::v-deep .el-table__body-wrapper::-webkit-scrollbar{
height: 10px!important;
}
::v-deep .el-table__fixed-right::before{
display: none; display: none;
} }
} ::v-deep .el-upload-list__item-name{
.uploadWrapper{
display: flex;
flex-direction: column;
align-items: flex-start;
}
}
::v-deep .el-table__body-wrapper::-webkit-scrollbar{
height: 10px!important;
}
::v-deep .el-table__fixed-right::before{
display: none;
}
::v-deep .el-upload-list__item-name{
color: #0a84ff;
.el-icon-document{
color: #0a84ff; color: #0a84ff;
.el-icon-document{
color: #0a84ff;
}
} }
} }
</style> </style>

View File

@ -39,6 +39,7 @@
@setFormItemData="setFormItemData" @setFormItemData="setFormItemData"
@getQuestions="getQuestions" @getQuestions="getQuestions"
@operateImageMarker="operateImageMarker" @operateImageMarker="operateImageMarker"
@unBindAnnotationToQuestion="unBindAnnotationToQuestion"
/> />
</template> </template>
@ -79,10 +80,11 @@
<script> <script>
import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation, saveTaskQuestion } from '@/api/trials' import { getCustomTableQuestionAnswer, changeDicomReadingQuestionAnswer, submitVisitTaskQuestionsInDto, getQuestionCalculateRelation, saveTaskQuestion } from '@/api/trials'
import { setSkipReadingCache, resetReadingTask } from '@/api/reading' import { setSkipReadingCache, resetReadingTask, saveTableQuestionMark } from '@/api/reading'
import const_ from '@/const/sign-code' import const_ from '@/const/sign-code'
import QuestionFormItem from './QuestionFormItem' import QuestionFormItem from './QuestionFormItem'
import SignForm from '@/views/trials/components/newSignForm' import SignForm from '@/views/trials/components/newSignForm'
import store from '@/store'
export default { export default {
name: 'EcrfList', name: 'EcrfList',
components: { components: {
@ -118,13 +120,15 @@ export default {
isBaseLineTask: false, isBaseLineTask: false,
rerender: true, rerender: true,
questionMarkInfoList: [], questionMarkInfoList: [],
operateStateEnum: null, // 012345 operateStateEnum: null, // 0123456
operateQuestionId: '', operateQuestionId: '',
operateRowId: '', operateRowId: '',
operateParentQsId: '',
isTableQuestion: false,
imageTool: '', imageTool: '',
imageToolAttribute: '', imageToolAttribute: '',
questionsMarkStatus: {}, questionsMarkStatus: {},
digitPlaces: 2 digitPlaces: 2,
} }
}, },
mounted() { mounted() {
@ -136,10 +140,10 @@ export default {
const digitPlaces = Number(localStorage.getItem('digitPlaces')) const digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
this.getQuestionCalculateRelation() this.getQuestionCalculateRelation()
this.getQuestions() this.getQuestions(true)
}, },
methods: { methods: {
async getQuestions() { async getQuestions(isInit) {
this.loading = true this.loading = true
try { try {
const param = { const param = {
@ -169,7 +173,9 @@ export default {
this.questions = res.Result.SinglePage this.questions = res.Result.SinglePage
this.questionsMarkStatus = {} this.questionsMarkStatus = {}
this.questionMarkInfoList = res.OtherInfo.QuestionMarkInfoList.map(i => { this.questionMarkInfoList = res.OtherInfo.QuestionMarkInfoList.map(i => {
if (i.QuestionId) { if (i.RowId) {
this.$set(this.questionsMarkStatus, `${i.RowId}_${i.TableQuestionId}`, {isMarked: i.MeasureData !== '', isSaved: true})
} else if (i.QuestionId) {
this.$set(this.questionsMarkStatus, i.QuestionId, {isMarked: i.MeasureData !== '', isSaved: true}) this.$set(this.questionsMarkStatus, i.QuestionId, {isMarked: i.MeasureData !== '', isSaved: true})
} }
if (typeof i.MeasureData === 'string' && i.MeasureData) { if (typeof i.MeasureData === 'string' && i.MeasureData) {
@ -177,6 +183,9 @@ export default {
} }
return i return i
}) })
if (!isInit) {
this.$emit('resetAnnotations', this.visitTaskId)
}
this.loading = false this.loading = false
} }
} catch (e) { } catch (e) {
@ -356,9 +365,12 @@ export default {
}, },
async operateImageMarker(obj) { async operateImageMarker(obj) {
this.operateStateEnum = obj.operateStateEnum this.operateStateEnum = obj.operateStateEnum
this.operateQuestionId = obj.question.Id this.isTableQuestion = obj.question.IsTableQuestion ? true : false
this.imageTool = obj.question.ImageTool this.imageTool = obj.question.ImageTool
this.imageToolAttribute = obj.question.ImageToolAttribute this.imageToolAttribute = obj.question.ImageToolAttribute
this.operateQuestionId = obj.question.Id
this.operateRowId = obj.question.RowId
this.operateParentQsId = obj.question.ParentQsId
if (obj.operateStateEnum === 0) { if (obj.operateStateEnum === 0) {
// //
this.$emit('setReadingToolPassive') this.$emit('setReadingToolPassive')
@ -367,7 +379,16 @@ export default {
this.$emit('setReadingToolActive', obj.question.ImageTool) this.$emit('setReadingToolActive', obj.question.ImageTool)
} else if (obj.operateStateEnum === 2) { } else if (obj.operateStateEnum === 2) {
// //
const i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id) let i = -1
if (this.isTableQuestion) {
if (this.operateRowId) {
i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === obj.question.Id && i.RowId === this.operateRowId)
} else {
i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === obj.question.Id && !i.RowId)
}
} else {
i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id)
}
if (i > -1) { if (i > -1) {
const annotation = this.questionMarkInfoList[i].MeasureData const annotation = this.questionMarkInfoList[i].MeasureData
this.$emit('viewCustomAnnotationSeries', { visitTaskId: this.visitTaskId, annotation }) this.$emit('viewCustomAnnotationSeries', { visitTaskId: this.visitTaskId, annotation })
@ -378,17 +399,29 @@ export default {
} else if (obj.operateStateEnum === 4) { } else if (obj.operateStateEnum === 4) {
this.$emit('setReadingToolPassive') this.$emit('setReadingToolPassive')
// //
this.$set(this.questionForm, obj.question.Id, '') let i = -1
const i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id) let questionMarkInfo = {}
if (i > -1) { if (this.isTableQuestion) {
this.questionMarkInfoList[i].MeasureData = '' if (this.operateRowId) {
this.questionMarkInfoList[i].StudyId = '' i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === obj.question.Id && i.RowId === this.operateRowId)
this.questionMarkInfoList[i].SeriesId = '' } else {
this.questionMarkInfoList[i].InstanceId = '' i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === obj.question.Id && !i.RowId)
}
} else {
this.$set(this.questionForm, obj.question.Id, '')
i = this.questionMarkInfoList.findIndex(i => i.QuestionId === obj.question.Id)
} }
this.$set(this.questionsMarkStatus, obj.question.Id, {isMarked: false, isSaved: false}) if (i === -1) return
this.questionMarkInfoList[i].MeasureData = ''
this.questionMarkInfoList[i].StudyId = ''
this.questionMarkInfoList[i].SeriesId = ''
this.questionMarkInfoList[i].InstanceId = ''
questionMarkInfo = this.questionMarkInfoList[i]
questionMarkInfo.isMarked = false
questionMarkInfo.isSaved = false
this.$set(this.questionsMarkStatus, this.operateRowId ? `${this.operateRowId}_${obj.question.Id}` : obj.question.Id, questionMarkInfo)
} else if (obj.operateStateEnum === 5) { } else if (obj.operateStateEnum === 5) {
// //
this.loading = true this.loading = true
try { try {
const answers = [] const answers = []
@ -400,6 +433,7 @@ export default {
obj.MeasureData = obj.MeasureData ? JSON.stringify(obj.MeasureData) : '' obj.MeasureData = obj.MeasureData ? JSON.stringify(obj.MeasureData) : ''
markInfo.push(obj) markInfo.push(obj)
} }
//
const params = { const params = {
visitTaskId: this.visitTaskId, visitTaskId: this.visitTaskId,
answers: answers, answers: answers,
@ -414,14 +448,93 @@ export default {
this.loading = false this.loading = false
} }
} else if (obj.operateStateEnum === 6) { } else if (obj.operateStateEnum === 6) {
// //
this.$set(this.questionsMarkStatus, obj.question.Id, {isMarked: false, isSaved: false}) let questionMarkInfo = {}
if (this.isTableQuestion) {
questionMarkInfo.isMarked = false
questionMarkInfo.isSaved = false
} else {
questionMarkInfo.isMarked = false
questionMarkInfo.isSaved = false
}
this.$set(this.questionsMarkStatus, this.operateRowId ? `${this.operateRowId}_obj.question.Id` : obj.question.Id, questionMarkInfo)
} else if (obj.operateStateEnum === 7) {
//
const loading = this.$loading({ fullscreen: true })
try {
let annotation = null
if (!this.operateRowId && this.operateQuestionId && obj.rowId) {
const i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === this.operateQuestionId && !i.RowId)
if (i === -1) return
this.questionMarkInfoList[i].RowId = obj.rowId
this.operateRowId = obj.rowId
annotation = this.questionMarkInfoList[i].MeasureData
let questionMarkStatus = Object.assign({}, this.questionsMarkStatus[this.operateQuestionId])
delete this.questionsMarkStatus[this.operateQuestionId]
this.$set(this.questionsMarkStatus, `${obj.rowId}_${this.operateQuestionId}`, questionMarkStatus)
} else if (this.operateRowId && this.operateQuestionId) {
const i = this.questionMarkInfoList.findIndex(i => i.RowId === this.operateRowId && i.TableQuestionId === this.operateQuestionId)
if (i === -1) return
annotation = this.questionMarkInfoList[i].MeasureData
}
let picturePath = ''
if (annotation) {
//
const base64Str = await this.getScreenshots({ visitTaskId: this.visitTaskId, annotation })
const pictureObj = await this.uploadScreenshots(`${new Date().getTime()}`, base64Str)
picturePath = pictureObj.isSuccess ? this.$getObjectName(pictureObj.result.url) : ''
}
let params = {
Answer: obj.answer,
VisitTaskId: this.visitTaskId,
QuestionId: obj.question.ParentQsId,
InstanceId: annotation ? annotation.instanceId : '',
SeriesId: annotation ? annotation.seriesId : '',
StudyId: annotation ? annotation.studyId : '',
MarkTool: annotation ? annotation.markTool : '',
PicturePath: picturePath,
NumberOfFrames: annotation ? annotation.numberOfFrames : null,
MeasureData: annotation ? JSON.stringify(annotation) : '',
QuestionType: 0,
OrderMarkName: annotation ? annotation.data.label : '',
RowId: this.operateRowId,
TableQuestionId: this.operateQuestionId,
RowIndex: obj.rowIndex
}
//
await saveTableQuestionMark(params, -10)
this.$set(this.questionsMarkStatus, `${this.operateRowId}_${this.operateQuestionId}`, {isMarked: annotation ? true : false, isSaved: true})
this.resetOperateState()
loading.close()
} catch(e) {
console.log(e)
loading.close()
}
} }
}, },
async bindAnnotationToQuestion(annotation) { async bindAnnotationToQuestion(annotation) {
console.log('bindAnnotationToQuestion')
try { try {
if (!(this.operateStateEnum === 0 || this.operateStateEnum === 1 || this.operateStateEnum === 3)) return if (!(this.operateStateEnum === null || this.operateStateEnum === 0 || this.operateStateEnum === 1 || this.operateStateEnum === 3)) return
if (this.operateStateEnum === 1 && annotation.markTool !== this.imageTool) return if (this.operateStateEnum === 1 && annotation.markTool !== this.imageTool) return
if (this.operateStateEnum === null) {
for(let i = 0; i < this.questionMarkInfoList.length; i++) {
if (this.questionMarkInfoList[i].MeasureData.annotationUID === annotation.annotationUID) {
this.questionMarkInfoList[i].MeasureData = annotation
if (this.questionMarkInfoList[i].TableQuestionId) {
store.dispatch('dicom3d/setOperateInfo', {annotation, parentQsId: this.questionMarkInfoList[i].QuestionId, questionId: this.questionMarkInfoList[i].TableQuestionId, rowId: this.questionMarkInfoList[i].RowId, imageToolAttribute: this.questionMarkInfoList[i].MarkTool})
let keyId = i > -1 && this.questionMarkInfoList[i].RowId ? `${this.questionMarkInfoList[i].RowId}_${this.questionMarkInfoList[i].TableQuestionId}` : this.questionMarkInfoList[i].TableQuestionId
this.$set(this.questionsMarkStatus, keyId, {isMarked: true, isSaved: false})
} else {
this.setAnswerToQuestion(annotation, this.questionMarkInfoList[i].QuestionId)
this.$set(this.questionsMarkStatus, this.questionMarkInfoList[i].QuestionId, {isMarked: true, isSaved: false})
}
}
}
return
}
if (!this.operateQuestionId) return if (!this.operateQuestionId) return
if (this.operateStateEnum === 0 || this.operateStateEnum === 3) { if (this.operateStateEnum === 0 || this.operateStateEnum === 3) {
if (!annotation.data.label) { if (!annotation.data.label) {
@ -432,6 +545,14 @@ export default {
this.$alert('该标记不能与问题绑定!') this.$alert('该标记不能与问题绑定!')
return return
} }
// rowId
if (this.operateStateEnum === 3) {
const i = this.questionMarkInfoList.findIndex(i=>i.MeasureData.annotationUID === annotation.annotationUID && i.RowId !== this.operateRowId)
if (i > -1) {
this.$alert('该标记已绑定到其他行,不能更改绑定!')
return
}
}
let msg = this.operateStateEnum === 0 ? '是否确认绑定?' : '是否确认更改?' let msg = this.operateStateEnum === 0 ? '是否确认绑定?' : '是否确认更改?'
const confirm = await this.$confirm(msg, { const confirm = await this.$confirm(msg, {
type: 'warning', type: 'warning',
@ -439,19 +560,26 @@ export default {
}) })
if (confirm !== 'confirm') return if (confirm !== 'confirm') return
} }
console.log('bindAnnotationToQuestion', annotation) let i = -1
if (this.isTableQuestion && this.operateRowId) {
const i = this.questionMarkInfoList.findIndex(i => i.QuestionId === this.operateQuestionId) i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === this.operateQuestionId && i.RowId === this.operateRowId)
} else if (this.isTableQuestion) {
i = this.questionMarkInfoList.findIndex(i => i.TableQuestionId === this.operateQuestionId && !i.RowId)
} else {
i = this.questionMarkInfoList.findIndex(i => i.QuestionId === this.operateQuestionId)
}
if (i === -1) { if (i === -1) {
const markInfo = { const markInfo = {
QuestionId: this.operateQuestionId,
InstanceId: annotation.instanceId, InstanceId: annotation.instanceId,
SeriesId: annotation.seriesId, SeriesId: annotation.seriesId,
StudyId: annotation.studyId, StudyId: annotation.studyId,
MarkTool: annotation.metadata.toolName, MarkTool: annotation.metadata.toolName,
PicturePath: '', PicturePath: '',
NumberOfFrames: annotation.numberOfFrames, NumberOfFrames: annotation.numberOfFrames,
MeasureData: annotation MeasureData: annotation,
RowId: this.operateRowId ? this.operateRowId : '',
QuestionId: this.isTableQuestion ? this.operateParentQsId : this.operateQuestionId,
TableQuestionId: this.isTableQuestion ? this.operateQuestionId : '',
} }
this.questionMarkInfoList.push(markInfo) this.questionMarkInfoList.push(markInfo)
} else { } else {
@ -463,8 +591,20 @@ export default {
this.questionMarkInfoList[i].NumberOfFrames = annotation.numberOfFrames this.questionMarkInfoList[i].NumberOfFrames = annotation.numberOfFrames
this.questionMarkInfoList[i].MeasureData = annotation this.questionMarkInfoList[i].MeasureData = annotation
} }
this.setAnswerToQuestion(annotation, this.operateQuestionId) let obj = null
this.$set(this.questionsMarkStatus, this.operateQuestionId, {isMarked: true, isSaved: false}) if (this.isTableQuestion) {
obj = {isMarked: true, isSaved: false}
store.dispatch('dicom3d/setOperateInfo', {annotation, parentQsId: this.operateParentQsId, questionId: this.operateQuestionId, rowId: this.operateRowId, imageToolAttribute: this.imageToolAttribute})
let keyId = i > -1 && this.questionMarkInfoList[i].RowId ? `${this.questionMarkInfoList[i].RowId}_${this.questionMarkInfoList[i].TableQuestionId}` : this.operateRowId ? `${this.operateRowId}_${this.operateQuestionId}` : this.operateQuestionId
this.$set(this.questionsMarkStatus, keyId, obj)
} else {
obj = {isMarked: true, isSaved: false}
this.setAnswerToQuestion(annotation, this.operateQuestionId)
this.$set(this.questionsMarkStatus, this.operateQuestionId, obj)
}
this.operateStateEnum === null
} catch (e) { } catch (e) {
console.log(e) console.log(e)
} }
@ -472,9 +612,25 @@ export default {
updateAnnotationToQuestion(annotation) { updateAnnotationToQuestion(annotation) {
const i = this.questionMarkInfoList.findIndex(i => i.MeasureData && i.MeasureData.annotationUID === annotation.annotationUID) const i = this.questionMarkInfoList.findIndex(i => i.MeasureData && i.MeasureData.annotationUID === annotation.annotationUID)
if (i === -1) return if (i === -1) return
this.questionMarkInfoList[i].measureData = annotation this.questionMarkInfoList[i].MeasureData = annotation
this.setAnswerToQuestion(annotation, this.questionMarkInfoList[i].QuestionId) let obj = null
this.$set(this.questionsMarkStatus, this.questionMarkInfoList[i].QuestionId, {isMarked: true, isSaved: false}) if (this.isTableQuestion || this.questionMarkInfoList[i].TableQuestionId) {
this.operateParentQsId = this.operateParentQsId ? this.operateParentQsId : this.questionMarkInfoList[i].QuestionId
this.operateQuestionId = this.operateQuestionId ? this.operateQuestionId : this.questionMarkInfoList[i].TableQuestionId
this.operateRowId = this.operateRowId ? this.operateRowId : this.questionMarkInfoList[i].RowId
this.imageToolAttribute = this.imageToolAttribute ? this.imageToolAttribute : annotation.metadata.toolName
obj = {isMarked: true, isSaved: false}
store.dispatch('dicom3d/setOperateInfo', {annotation, parentQsId: this.operateParentQsId, questionId: this.operateQuestionId, rowId: this.operateRowId, imageToolAttribute: this.imageToolAttribute})
let keyId = this.questionMarkInfoList[i].RowId ? `${this.questionMarkInfoList[i].RowId}_${this.questionMarkInfoList[i].TableQuestionId}` : this.questionMarkInfoList[i].TableQuestionId
this.$set(this.questionsMarkStatus, keyId, obj)
} else {
obj = {isMarked: true, isSaved: false}
this.setAnswerToQuestion(annotation, this.questionMarkInfoList[i].QuestionId)
this.$set(this.questionsMarkStatus, this.questionMarkInfoList[i].QuestionId, obj)
}
}, },
setAnswerToQuestion(annotation, questionId) { setAnswerToQuestion(annotation, questionId) {
if (!questionId || !annotation) return if (!questionId || !annotation) return
@ -495,6 +651,61 @@ export default {
} }
} }
}, },
unBindAnnotationToQuestion(obj) {
const { markTableQuestions = [], questionId } = obj || {}
const { questionMarkInfoList, questionsMarkStatus } = this
if (!Array.isArray(markTableQuestions) || !questionId || !Array.isArray(questionMarkInfoList)) {
return
}
this.questionMarkInfoList = questionMarkInfoList.filter(item => {
const { TableQuestionId, QuestionId } = item || {}
if ((TableQuestionId && QuestionId === questionId && markTableQuestions.includes(TableQuestionId))) {
if (questionsMarkStatus && questionsMarkStatus[TableQuestionId]) {
delete questionsMarkStatus[TableQuestionId]
}
} else {
return
}
})
},
//
getScreenshots(obj) {
return new Promise((resolve, reject) => {
this.$emit('getCustomScreenshots', obj, resolve) // resolve
})
},
async uploadScreenshots(fileName, file) {
try {
file = this.convertBase64ToBlob(file)
const trialId = this.$route.query.trialId
const taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
const subjectId = taskInfo.SubjectId
const result = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${fileName}.png`, file)
return { isSuccess: true, result: result }
} catch (e) {
console.log(e)
return { isSuccess: false, result: e }
}
},
convertBase64ToBlob(imageEditorBase64) {
const base64Arr = imageEditorBase64.split(',')
let imgtype = ''
let base64String = ''
if (base64Arr.length > 1) {
base64String = base64Arr[1]
imgtype = base64Arr[0].substring(
base64Arr[0].indexOf(':') + 1,
base64Arr[0].indexOf(';')
)
}
const bytes = atob(base64String)
const bytesCode = new ArrayBuffer(bytes.length)
const byteArray = new Uint8Array(bytesCode)
for (let i = 0; i < bytes.length; i++) {
byteArray[i] = bytes.charCodeAt(i)
}
return new Blob([bytesCode], { type: imgtype })
},
resetOperateState() { resetOperateState() {
console.log('resetOperateState') console.log('resetOperateState')
this.operateStateEnum = null this.operateStateEnum = null
@ -513,13 +724,14 @@ export default {
} }
) )
if (confirm !== 'confirm') return if (confirm !== 'confirm') return
this.$emit('setReadingToolPassive')
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
try { try {
const res = await resetReadingTask({ visitTaskId: this.visitTaskId }) const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
if (res.IsSuccess) { if (res.IsSuccess) {
this.rerender = false this.rerender = false
await this.getQuestionCalculateRelation() await this.getQuestionCalculateRelation()
await this.getQuestions() await this.getQuestions(true)
this.$emit('resetAnnotations', this.visitTaskId) this.$emit('resetAnnotations', this.visitTaskId)
this.$nextTick(() => { this.$nextTick(() => {
this.rerender = true this.rerender = true

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="criterion-form-item"> <div class="criterion-table-form-item">
<el-form-item <el-form-item
v-if="(question.ShowQuestion===1 && !!~question.ParentTriggerValueList.indexOf(questionForm[question.ParentId])) || question.ShowQuestion===0" v-if="(question.ShowQuestion===1 && !!~question.ParentTriggerValueList.indexOf(questionForm[question.ParentId])) || question.ShowQuestion===0"
:label="`${question.QuestionName}`" :label="`${question.QuestionName}`"
@ -142,26 +142,100 @@
disabled disabled
/> />
<!-- 数值 --> <!-- 数值 -->
<!-- :precision="2" :step="0.1" :max="10" --> <template v-if="question.Type === 'number' && (question.ImageMarkEnum === 1 || question.ImageMarkEnum === 2)">
<el-input <div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
type="number" <el-input
v-if="question.Type === 'number' && question.DataSource !== 1" type="number"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')" @change="(val) => { formItemNumberChange(val, question) }"
@change="((val)=>{formItemNumberChange(val, question)})" @blur="questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked ? ()=>{} : handleMarkedQsBlur(questionForm[question.Id], questionForm, question.Id, question) "
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)" v-model="questionForm[question.Id]"
v-model="questionForm[question.Id]" :disabled="(questionsMarkStatus[question.Id] && questionsMarkStatus[question.Id].isMarked && question.ImageMarkEnum === 2) || question.ImageMarkEnum === 1"
> style="width: 150px;"
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template> >
</el-input> <template v-if="question.Unit !== 0" slot="append">
<el-input {{ question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit }}
type="number" </template>
v-if="question.Type === 'number' && question.DataSource === 1" </el-input>
:disabled="question.DataSource === 1" <!-- 测量 -->
@blur="handleCalculationBlur(calculationValue)" <el-button
v-model="calculationValue" v-if="readingTaskState < 2 && (!questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] || (questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && !questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isMarked))"
> size="mini"
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template> type="text"
</el-input> @click="operateImageMarker({operateStateEnum: 1, question})"
>
测量
</el-button>
<!-- 绑定 -->
<el-button
v-if="readingTaskState < 2 && (!questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] || (questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && !questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isMarked))"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 0, question})"
>
绑定
</el-button>
<!-- 查看 -->
<el-button
v-if="questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isMarked"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 2, question})"
>
查看
</el-button>
<!-- 更改 -->
<el-button
v-if="readingTaskState < 2 && (questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isMarked)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 3, question})"
>
更改
</el-button>
<!-- 移除 -->
<el-button
v-if="readingTaskState < 2 && (questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isMarked)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 4, question})"
>
移除
</el-button>
<!-- 保存 -->
<el-button
v-if="readingTaskState < 2 && (questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && !questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isSaved)"
size="mini"
type="text"
@click="operateImageMarker({operateStateEnum: 7, question})"
>
<el-tooltip v-if="questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id] && !questionsMarkStatus[rowId ? `${rowId}_${question.Id}` : question.Id].isSaved" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<i class="el-icon-warning" style="color:red" />
</el-tooltip>
保存
</el-button>
</div>
</template>
<template v-else-if="question.Type === 'number'">
<el-input
type="number"
v-if="question.Type === 'number' && question.DataSource !== 1"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')"
@change="((val)=>{formItemNumberChange(val, question)})"
@blur="handleBlur(questionForm[question.Id], questionForm, question.Id)"
v-model="questionForm[question.Id]"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
</el-input>
<el-input
type="number"
v-if="question.Type === 'number' && question.DataSource === 1"
:disabled="question.DataSource === 1"
@blur="handleCalculationBlur(calculationValue)"
v-model="calculationValue"
>
<template slot="append" v-if="question.Unit !== 0">{{question.Unit !== 4 ? $fd('ValueUnit', question.Unit) : question.CustomUnit}}</template>
</el-input>
</template>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload <el-upload
v-if="question.Type==='upload'" v-if="question.Type==='upload'"
@ -231,6 +305,7 @@
</div> </div>
</template> </template>
<script> <script>
import { submitTableQuestion } from '@/api/trials'
export default { export default {
name: 'QuestionTableFormItem', name: 'QuestionTableFormItem',
props: { props: {
@ -271,7 +346,17 @@ export default {
type: { type: {
type: String, type: String,
default: 'add' default: 'add'
} },
questionsMarkStatus: {
type: Object,
default() {
return {}
}
},
parentQsId: {
type: String,
default: ''
},
}, },
computed: { computed: {
calculationValue: { calculationValue: {
@ -294,7 +379,8 @@ export default {
organList: [], organList: [],
QuestionsList: [], QuestionsList: [],
QuestionsForm: {}, QuestionsForm: {},
digitPlaces: 2 digitPlaces: 2,
rowId: ''
} }
}, },
watch: { watch: {
@ -307,10 +393,19 @@ export default {
// } catch (e) { // } catch (e) {
// } // }
// this.formItemNumberChange(this.question.Id, false) // this.formItemNumberChange(this.question.Id, false)
this.rowId = this.questionForm.RowId
} }
}, },
questionsMarkStatus: {
deep: true,
immediate: true,
handler(v) {
// console.log(v, this.rowId)
}
}
}, },
mounted() { mounted() {
var digitPlaces = Number(localStorage.getItem('digitPlaces')) var digitPlaces = Number(localStorage.getItem('digitPlaces'))
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
if (this.question.Type === 'upload') { if (this.question.Type === 'upload') {
@ -356,6 +451,11 @@ export default {
handleBlur(value, a, b) { handleBlur(value, a, b) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces)) this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
}, },
handleMarkedQsBlur(value, a, b, question) {
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
question.IsTableQuestion = true
// this.$emit('operateImageMarker', {operateStateEnum: 6, question})
},
handleCalculationBlur(v) { handleCalculationBlur(v) {
this.calculationValue = parseFloat(v).toFixed(this.digitPlaces) this.calculationValue = parseFloat(v).toFixed(this.digitPlaces)
}, },
@ -477,6 +577,39 @@ export default {
setFormItemData(obj) { setFormItemData(obj) {
this.$emit('setFormItemData', obj) this.$emit('setFormItemData', obj)
}, },
async operateImageMarker(obj) {
obj.question.IsTableQuestion = true
obj.question.RowId = this.rowId
obj.question.ParentQsId = this.parentQsId
if (obj.operateStateEnum === 7) {
//
// if (!obj.question.RowId) {
// // rowId
// const loading = this.$loading({ fullscreen: true })
// try {
// let params = {
// questionId: this.parentQsId,
// RowIndex: this.questionForm.RowIndex,
// visitTaskId: this.visitTaskId,
// trialId: this.$route.query.trialId,
// answerList: [],
// }
// let res = await submitTableQuestion(params)
// // this.$emit('save',rowId)
// this.QuestionsForm.RowId = res.Result.RowId
// obj.rowId = res.Result.RowId
// this.rowId = res.Result.RowId
// loading.close()
// } catch(e) {
// loading.close()
// }
// }
obj.rowIndex = this.questionForm.RowIndex
// obj.parentQsId = this.parentQsId
obj.answer = this.questionForm[obj.question.Id]
}
this.$emit('operateImageMarker', obj)
},
async uploadScreenshot(param) { async uploadScreenshot(param) {
if (!this.visitTaskId) return if (!this.visitTaskId) return
const loading = this.$loading({ const loading = this.$loading({
@ -541,25 +674,19 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.my_dialog{
.criterion-form-item{ .criterion-table-form-item{
::v-deep .el-form-item__content{
width: auto;
}
}
}
.criterion-form-item{
.el-form-item{ .el-form-item{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
align-items: flex-start; align-items: flex-start;
} }
::v-deep .el-form-item__content{
width: 500px;
}
.el-input{ .el-input{
width:100%; width:100%;
} }
.el-select {
width:100%;
}
.mb{ .mb{
margin-bottom: 0px; margin-bottom: 0px;
} }