阅片页面表格内层问题,部分问题无法使用(截图、附件修改)
continuous-integration/drone/push Build is passing Details

main
wangxiaoshuang 2025-07-22 11:53:28 +08:00
parent 5ef755249c
commit eab207fc35
2 changed files with 117 additions and 81 deletions

View File

@ -21,7 +21,7 @@
<el-table-column :prop="item.Id" :label="item.QuestionName" :key="item.Id" <el-table-column :prop="item.Id" :label="item.QuestionName" :key="item.Id"
v-for="item of question.TableQuestions.Questions" show-overflow-tooltip :render-header="renderHeader"> v-for="item of question.TableQuestions.Questions" show-overflow-tooltip :render-header="renderHeader">
<template slot-scope="scope"> <template slot-scope="scope">
<span v-if="item.Type === 'upload'"> <span v-if="item.Type === 'upload' || item.Type === 'screenshot'">
{{ scope.row[item.Id] === '' ? '' : scope.row[item.Id] ? scope.row[item.Id].split('|').length : '' }} {{ scope.row[item.Id] === '' ? '' : scope.row[item.Id] ? scope.row[item.Id].split('|').length : '' }}
</span> </span>
<span v-else-if="item.Type === 'number'"> <span v-else-if="item.Type === 'number'">
@ -82,7 +82,8 @@
validator: question.Type === 'number' && !question.TypeValue ? validatorNumberInput : (rule, value, callback) => { callback() }, validator: question.Type === 'number' && !question.TypeValue ? validatorNumberInput : (rule, value, callback) => { callback() },
trigger: ['blur', 'change'] trigger: ['blur', 'change']
} }
]" :class="[question.Type === 'group' ? 'mb' : question.Type === 'upload' ? 'uploadWrapper' : '']"> ]"
:class="[question.Type === 'group' ? 'mb' : question.Type === 'upload' || question.Type === 'screenshot' ? 'uploadWrapper' : '']">
<!-- 输入框 --> <!-- 输入框 -->
<el-input v-if="question.Type === 'input'" v-model="questionForm[question.Id]" <el-input v-if="question.Type === 'input'" v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2 || readingTaskState === 2" /> :disabled="question.TableQuestionType === 2 || readingTaskState === 2" />
@ -237,18 +238,18 @@
</el-input> </el-input>
</template> </template>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload v-if="question.Type === 'upload'" :disabled="readingTaskState === 2" action <el-upload v-if="question.Type === 'upload' || question.Type === 'screenshot'"
:accept="question.FileType" :limit="question.ImageCount === 0 ? 100 : question.ImageCount" :disabled="readingTaskState === 2" action :accept="question.FileType"
:on-preview="handlePictureCardPreview" :limit="question.ImageCount === 0 ? 100 : question.ImageCount" :on-preview="handlePictureCardPreview"
:before-upload="(file) => { return handleBeforeUpload(file, question.FileType) }" :before-upload="(file) => { return handleBeforeUpload(file, question.FileType, question.Type) }"
:http-request="uploadScreenshot" :on-remove="handleRemove" :file-list="fileList" :http-request="uploadScreenshot" :on-remove="handleRemove" :file-list="fileList"
:class="{ disabled: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount }"> :class="{ disabled: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount }">
<el-button slot="default" class="el-icon-plus" v-if="readingTaskState < 2"> <el-button slot="default" class="el-icon-plus" v-if="readingTaskState < 2">
{{ this.$t('common:button:upload') }} {{ this.$t('common:button:upload') }}
</el-button> </el-button>
</el-upload> </el-upload>
<viewer v-if="question.Type === 'upload' && imgVisible" :ref="imageUrl" style="margin:0 10px;" <viewer v-if="(question.Type === 'upload' || question.Type === 'screenshot') && imgVisible" :ref="imageUrl"
:images="[imageUrl]"> style="margin:0 10px;" :images="[imageUrl]">
<img v-show="false" crossorigin="anonymous" :src="imageUrl" alt="Image"> <img v-show="false" crossorigin="anonymous" :src="imageUrl" alt="Image">
</viewer> </viewer>
</el-form-item> </el-form-item>
@ -275,24 +276,28 @@
</base-model> --> </base-model> -->
<!-- 预览文件 --> <!-- 预览文件 -->
<el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="$t('common:button:preview')" <!-- <el-dialog v-if="previewVisible" :visible.sync="previewVisible" :title="$t('common:button:preview')"
:fullscreen="true" append-to-body custom-class="base-dialog-wrapper"> :fullscreen="true" append-to-body custom-class="base-dialog-wrapper">
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px"> <div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
<PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" /> <PreviewFile v-if="previewVisible" :file-path="currentPath" :file-type="currentType" />
</div> </div>
</el-dialog> </el-dialog> -->
</div> </div>
</template> </template>
<script> <script>
import { deleteReadingRowAnswer, getQuestionCalculateRelation, submitTableQuestion, deleteCustomTag } 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 { mapGetters } from 'vuex'
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent' import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
export default { export default {
name: 'QuestionFormItem', name: 'QuestionFormItem',
components: { QuestionTableFormItem, BaseModel, PreviewFile }, components: {
QuestionTableFormItem,
BaseModel,
// PreviewFile
},
props: { props: {
isBaseline: { isBaseline: {
type: Boolean, type: Boolean,
@ -355,9 +360,9 @@ export default {
digitPlaces: 2, digitPlaces: 2,
CalculationTabelList: [], CalculationTabelList: [],
classArr: [], classArr: [],
previewVisible: false, // previewVisible: false,
currentPath: '', // currentPath: '',
currentType: '', // currentType: '',
markTableQuestions: [], markTableQuestions: [],
parentQsId: '' parentQsId: ''
} }
@ -441,12 +446,14 @@ export default {
// } // }
// } // }
// }, 300) // }, 300)
if (this.question.Type === 'upload') { if (this.question.Type === 'upload' || this.question.Type === 'screenshot') {
if (this.questionForm[this.question.Id]) { if (this.questionForm[this.question.Id]) {
this.urls = this.questionForm[this.question.Id].split('|') this.urls = this.questionForm[this.question.Id].split('|')
this.fileList = [] this.fileList = []
this.urls.map((url, index) => { this.urls.map((url, index) => {
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${index + 1}`, url: `${url}` }) var index = url.lastIndexOf('.')
var suffix = url.substring(index + 1, url.length)
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${index + 1}(${suffix})`, url: `${url}` })
}) })
} }
} }
@ -1249,9 +1256,11 @@ export default {
spinner: 'el-icon-loading' spinner: 'el-icon-loading'
}) })
var fileName = param.file.name var fileName = param.file.name
var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, url.length)
let file = await this.fileToBlob(param.file) let file = await this.fileToBlob(param.file)
let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file) let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file)
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}`, url: this.$getObjectName(res.url) }) this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}(${suffix})`, url: this.$getObjectName(res.url) })
this.urls.push(this.$getObjectName(res.url)) this.urls.push(this.$getObjectName(res.url))
this.$emit("setFormItemData", { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question }) this.$emit("setFormItemData", { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
this.$set(this.QuestionsForm, this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '') this.$set(this.QuestionsForm, this.question.Id, this.urls.length > 0 ? this.urls.join('|') : '')
@ -1267,7 +1276,10 @@ export default {
// loading.close() // loading.close()
// }) // })
}, },
handleBeforeUpload(file, accept) { handleBeforeUpload(file, accept, type) {
if (type === 'screenshot') {
accept = '.png,.jpeg,.jpg'
}
// //
if (this.checkFileSuffix(file.name, accept) || accept === '-1') { if (this.checkFileSuffix(file.name, accept) || accept === '-1') {
return true return true
@ -1290,11 +1302,27 @@ export default {
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
var suffix = file.url.substring(file.url.lastIndexOf(".") + 1) var suffix = file.url.substring(file.url.lastIndexOf(".") + 1)
suffix = suffix ? suffix.toLowerCase() : '' suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf') { if (['ppt',
'pptx',
'doc',
'docx',
'xls',
'xlsx'].includes(suffix)) {
// window.open(this.OSSclientConfig.basePath + file.url,'_blank') // window.open(this.OSSclientConfig.basePath + file.url,'_blank')
this.currentPath = file.url this.$onlyOffice({
this.currentType = suffix path: file.url,
this.previewVisible = true type: suffix,
title: file.name
})
// this.currentPath = file.url
// this.currentType = suffix
// this.previewVisible = true
} else if (['pdf'].includes(suffix)) {
this.$preview({
path: file.url,
type: 'pdf',
title: file.name,
})
} else { } else {
this.imageUrl = this.OSSclientConfig.basePath + file.url this.imageUrl = this.OSSclientConfig.basePath + file.url
this.imgVisible = true this.imgVisible = true

View File

@ -11,7 +11,8 @@
validator: question.Type === 'number' && !question.TypeValue ? validatorNumberInput : (rule, value, callback) => { callback() }, validator: question.Type === 'number' && !question.TypeValue ? validatorNumberInput : (rule, value, callback) => { callback() },
trigger: ['blur', 'change'] trigger: ['blur', 'change']
} }
]" :class="[question.Type === 'group' ? 'mb' : question.Type === 'upload' ? 'uploadWrapper' : '']"> ]"
:class="[question.Type === 'group' ? 'mb' : question.Type === 'upload' || question.Type === 'screenshot' ? 'uploadWrapper' : '']">
<!-- 输入框 --> <!-- 输入框 -->
<el-input v-if="question.Type === 'input'" v-model="questionForm[question.Id]" <el-input v-if="question.Type === 'input'" v-model="questionForm[question.Id]"
:disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')" /> :disabled="question.TableQuestionType === 2 || (question.IsCopy && type === 'edit' && !isBaseline && questionForm.IsCurrentTaskAdd === 'False')" />
@ -157,41 +158,20 @@
</el-input> </el-input>
</template> </template>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload v-if="question.Type === 'upload'" action :accept="question.FileType" <el-upload v-if="question.Type === 'upload' || question.Type === 'screenshot'" :disabled="readingTaskState === 2"
:limit="question.ImageCount === 0 ? 100 : question.ImageCount" :on-preview="handlePictureCardPreview" action :accept="question.FileType" :limit="question.ImageCount === 0 ? 100 : question.ImageCount"
:before-upload="handleBeforeUpload" :http-request="uploadScreenshot" list-type="picture-card" :on-preview="handlePictureCardPreview"
:on-remove="handleRemove" :file-list="fileList" :before-upload="(file) => { return handleBeforeUpload(file, question.FileType, question.Type) }"
:http-request="uploadScreenshot" :on-remove="handleRemove" :file-list="fileList"
:class="{ disabled: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount }"> :class="{ disabled: question.ImageCount === 0 ? false : fileList.length >= question.ImageCount }">
<i slot="default" class="el-icon-plus" /> <el-button slot="default" class="el-icon-plus" v-if="readingTaskState < 2">
<div slot="file" slot-scope="{file}"> {{ this.$t('common:button:upload') }}
<viewer :ref="file.url" :images="[imageUrl]" style=" </el-button>
display: flex;
align-items: center;
justify-content: center;
width: 100%;
height: 100%;
">
<img class="el-upload-list__item-thumbnail" :src="OSSclientConfig.basePath + file.url"
crossOrigin="anonymous" alt="" style="max-width: 100%; max-height: 100%" />
<span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)">
<i class="el-icon-zoom-in" />
</span>
<span v-if="readingTaskState < 2" class="el-upload-list__item-delete" @click="handleRemove(file)">
<i class="el-icon-delete" />
</span>
</span>
</viewer>
</div>
</el-upload> </el-upload>
<el-dialog v-if="question.Type === 'upload'" append-to-body :visible.sync="imgVisible" width="600px"> <viewer v-if="(question.Type === 'upload' || question.Type === 'screenshot') && imgVisible" :ref="imageUrl"
<el-image :src="imageUrl" width="100%"> style="margin:0 10px;" :images="[imageUrl]">
<div slot="placeholder" class="image-slot"> <img v-show="false" crossorigin="anonymous" :src="imageUrl" alt="Image">
{{ $t('trials:readingUnit:qsList:message:loading') }}<span class="dot">...</span> </viewer>
</div>
</el-image>
</el-dialog>
</el-form-item> </el-form-item>
</div> </div>
</template> </template>
@ -298,12 +278,14 @@ export default {
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' || this.question.Type === 'screenshot') {
if (this.questionForm[this.question.Id]) { if (this.questionForm[this.question.Id]) {
this.urls = this.questionForm[this.question.Id].split('|') this.urls = this.questionForm[this.question.Id].split('|')
this.fileList = [] this.fileList = []
this.urls.map(url => { this.urls.map((url, index) => {
this.fileList.push({ name: '', url: `${url}` }) var index = url.lastIndexOf('.')
var suffix = url.substring(index + 1, url.length)
this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${index + 1}(${suffix})`, url: `${url}` })
}) })
} }
} }
@ -575,32 +557,33 @@ export default {
text: 'Loading', text: 'Loading',
spinner: 'el-icon-loading' spinner: 'el-icon-loading'
}) })
var trialId = this.$route.query.trialId var fileName = param.file.name
var subjectId = this.$route.query.trialId var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length)
var file = await this.fileToBlob(param.file) var file = await this.fileToBlob(param.file)
const res = await this.OSSclient.put(`/${trialId}/Read/${subjectId}/Visit/${param.file.name}`, file) let res = await this.OSSclient.put(`/${this.$route.query.trialId}/Customize/${this.visitTaskId}/${fileName}`, file)
this.fileList.push({ name: param.file.name, path: this.$getObjectName(res.url), url: this.$getObjectName(res.url) }) this.fileList.push({ name: `${this.$t('trials:emailManageCfg:title:fileName')}${this.fileList.length + 1}(${suffix})`, url: this.$getObjectName(res.url) })
this.urls.push(this.$getObjectName(res.url)) this.urls.push(this.$getObjectName(res.url))
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question }) this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
loading.close() loading.close()
}, },
handleBeforeUpload(file) { handleBeforeUpload(file, accept, type) {
if (type === 'screenshot') {
accept = '.png,.jpeg,.jpg'
}
// //
if (this.checkFileSuffix(file.name)) { if (this.checkFileSuffix(file.name, accept) || accept === '-1') {
// this.fileList = []
return true return true
} else { } else {
let msg = this.$t( const msg = this.$t('trials:adReview:title:msg4').replace('xxx', accept)
"trials:readingUnit:qsList:message:imageFormat"
).replace("xxx", this.question.FileType)
this.$alert(msg) this.$alert(msg)
return false return false
} }
}, },
checkFileSuffix(fileName) { checkFileSuffix(fileName, accept) {
var index = fileName.lastIndexOf('.') var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length) var suffix = fileName.substring(index + 1, fileName.length)
if (this.question.FileType.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) { if (accept.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false return false
} else { } else {
return true return true
@ -610,21 +593,46 @@ export default {
handlePictureCardPreview(file) { handlePictureCardPreview(file) {
var suffix = file.url.substring(file.url.lastIndexOf(".") + 1) var suffix = file.url.substring(file.url.lastIndexOf(".") + 1)
suffix = suffix ? suffix.toLowerCase() : '' suffix = suffix ? suffix.toLowerCase() : ''
if (suffix === 'doc' || suffix === 'docx' || suffix === 'pdf') { if (['ppt',
window.open(this.OSSclientConfig.basePath + file.url, '_blank') 'pptx',
'doc',
'docx',
'xls',
'xlsx'].includes(suffix)) {
// window.open(this.OSSclientConfig.basePath + file.url,'_blank')
this.$onlyOffice({
path: file.url,
type: suffix,
title: file.name
})
// this.currentPath = file.url
// this.currentType = suffix
// this.previewVisible = true
} else if (['pdf'].includes(suffix)) {
this.$preview({
path: file.url,
type: 'pdf',
title: file.name,
})
} else { } else {
this.imageUrl = this.OSSclientConfig.basePath + file.url this.imageUrl = this.OSSclientConfig.basePath + file.url
// this.imgVisible = true this.imgVisible = true
this.$refs[file.url].$viewer.show() this.$nextTick(() => {
this.$refs[this.imageUrl].$viewer.show()
})
} }
}, },
// //
handleRemove(file, fileList) { handleRemove(file, fileList) {
this.imageUrl = '' if (file && file.status === "success") {
this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1) this.imageUrl = ''
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1) this.fileList.splice(this.fileList.findIndex(f => f.url === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question }) this.fileList.forEach((i, index) => {
i.name = `${this.$t('trials:emailManageCfg:title:fileName')}${index + 1}`
})
this.urls.splice(this.fileList.findIndex(f => f === file.url), 1)
this.$emit('setFormItemData', { key: this.question.Id, val: this.urls.length > 0 ? this.urls.join('|') : '', question: this.question })
}
} }
} }
} }