Compare commits

...

31 Commits
rj ... main

Author SHA1 Message Date
caiyiling 45c0e5030b Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2026-07-10 17:54:12 +08:00
caiyiling 36e23b8135 通知列表添加默认排序 2026-07-10 17:53:50 +08:00
wangxiaoshuang b530f68446 1
continuous-integration/drone/push Build is passing Details
2026-07-10 17:11:39 +08:00
wangxiaoshuang 383bfabae8 1
continuous-integration/drone/push Build is passing Details
2026-07-10 16:59:18 +08:00
wangxiaoshuang 196ed7f993 完全随机ir上传下载页面及预览页屏蔽受试者编号和项目编号
continuous-integration/drone/push Build is passing Details
2026-07-10 16:53:41 +08:00
caiyiling 70cc0027cd 受试者状态更改弹窗移除结束访视日期
continuous-integration/drone/push Build is passing Details
2026-07-10 16:21:44 +08:00
caiyiling 975b7d39a7 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2026-07-10 15:06:24 +08:00
caiyiling 21bcd1fddb 只有顺序阅片的时显示是否复制后续任务阅片表单 2026-07-10 15:05:39 +08:00
wangxiaoshuang 04bbde8583 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web 2026-07-10 13:55:06 +08:00
wangxiaoshuang f3c4bedbfd 趋势图提示红色改为蓝色 2026-07-10 13:54:54 +08:00
caiyiling 835aedc800 1
continuous-integration/drone/push Build is passing Details
2026-07-10 13:40:57 +08:00
caiyiling 9026b1d7fd 自定义标准完全随机阅片更改
continuous-integration/drone/push Build is passing Details
2026-07-10 13:12:44 +08:00
caiyiling b8f96efa66 列表调整
continuous-integration/drone/push Build is passing Details
2026-07-10 11:18:05 +08:00
caiyiling 4c4f68dbd0 完全随机阅片规则更改
continuous-integration/drone/push Build is passing Details
2026-07-10 11:12:55 +08:00
caiyiling 11c56d2f7a 1
continuous-integration/drone/push Build is passing Details
2026-07-09 16:52:58 +08:00
caiyiling a72521304e Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2026-07-09 16:33:50 +08:00
caiyiling 8baf6cb88f IR阅片模块相关页面添加任务名称搜索条件 2026-07-09 16:33:14 +08:00
wangxiaoshuang 71e04c3bf1 中心调研移动端确认弹框样式修改
continuous-integration/drone/push Build is passing Details
2026-07-09 15:17:44 +08:00
caiyiling 1af9b48622 完全随机IR阅片列表及阅片页面更改
continuous-integration/drone/push Build is pending Details
2026-07-09 14:17:02 +08:00
wangxiaoshuang 447b74fa55 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web
continuous-integration/drone/push Build is passing Details
2026-07-09 13:29:51 +08:00
wangxiaoshuang c633fbcf87 外层问题配置为表格问题不显示时阅片时不展示表格 2026-07-09 13:29:45 +08:00
caiyiling 1cc57ad1d6 修复保存申请重阅表单异常问题
continuous-integration/drone/push Build is passing Details
2026-07-09 09:30:19 +08:00
caiyiling f282fdfabc 是否复制后续表单去除标准限制
continuous-integration/drone/push Build is passing Details
2026-07-08 16:46:50 +08:00
caiyiling d77c6ecf03 Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is passing Details
2026-07-08 16:04:27 +08:00
caiyiling 1db75cf4f7 MRI-PDFF报告页数据更改 2026-07-08 16:03:55 +08:00
wangxiaoshuang 7bc70bfd6c 【中心调研】中心调研表手机扫描二维码进入时,同pc一样也需要增加验证。上传文件功能也要能正常使用
continuous-integration/drone/push Build is passing Details
2026-07-07 17:35:33 +08:00
wangxiaoshuang 69ba30e5a9 【趋势图】趋势图访视结果后增加查看按钮,可以查看已阅结果
continuous-integration/drone/push Build is passing Details
2026-07-07 10:25:32 +08:00
wangxiaoshuang 18482ddaa9 【中心调研】选择项目方案号生成验证码,项目方案号中有特殊符号,生成的验证码中未显示特殊符号
continuous-integration/drone/push Build is passing Details
2026-07-07 09:38:14 +08:00
caiyiling 14e2afcfee Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/irc_web into main
continuous-integration/drone/push Build is pending Details
2026-07-06 17:22:30 +08:00
caiyiling 39dadbbf47 受试者任务状态变更原因更改 2026-07-06 17:20:59 +08:00
wangxiaoshuang d0ba340fea 去除分割上传文件按钮
continuous-integration/drone/push Build is passing Details
2026-07-06 11:44:37 +08:00
38 changed files with 1203 additions and 446 deletions

View File

@ -34,8 +34,8 @@
</div>
<div class="info-subject">
<div v-if="series.subjectCode">{{ series.subjectCode }}</div>
<div v-if="series.visitName">{{ series.visitName }}</div>
<div v-if="series.subjectCode && IsReadingTaskViewInOrder !== 0">{{ series.subjectCode }}</div>
<div v-if="series.visitName && IsReadingTaskViewInOrder !== 0">{{ series.visitName }}</div>
<div>{{ stack.description }}</div>
<!-- <div>{{ dicomInfo.hospital }}</div> -->
<!-- <div v-show="dicomInfo.pid">{{ dicomInfo.pid }}</div> -->
@ -174,7 +174,8 @@ export default {
orientationMarkers: [],
originalMarkers: [],
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') },
tip: ''
tip: '',
IsReadingTaskViewInOrder: 2
}
},
@ -182,6 +183,9 @@ export default {
this.type = this.$router.currentRoute.query.type
? this.$router.currentRoute.query.type
: ''
if (this.$router.currentRoute.query.IsReadingTaskViewInOrder) {
this.IsReadingTaskViewInOrder = Number(this.$router.currentRoute.query.IsReadingTaskViewInOrder)
}
this.canvas = this.$refs.canvas
this.canvas.addEventListener('cornerstonenewimage', this.onNewImage)
this.canvas.addEventListener(

View File

@ -33,7 +33,7 @@
<el-table-column type="index" width="40" />
<!--受试者-->
<el-table-column :label="$t('download:table:subjectCode')" min-width="130" prop="SubjectCode"
show-overflow-tooltip />
show-overflow-tooltip v-if="isReadingTaskViewInOrder !== 0" />
<!--访视名称-->
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" sortable v-if="IsImageSegment" />
<!--任务名称-->
@ -78,7 +78,7 @@
</el-table>
<study-view v-if="model_cfg.visible" :model_cfg="model_cfg" :modelList="modelList" :bodyPart="bodyPart"
:subjectVisitId="modelSubjectVisitId" :IsDicom="IsDicom" :isDownload="true" :visitTaskId="modelTaskId"
:IsImageSegment="IsImageSegment" :Criterion="Criterion" />
:IsImageSegment="IsImageSegment" :Criterion="Criterion" :IsReadingTaskViewInOrder="isReadingTaskViewInOrder" />
</el-dialog>
</template>
<script>
@ -136,7 +136,11 @@ export default {
IsImageSegment: {
type: Boolean,
default: false,
}
},
isReadingTaskViewInOrder: {
type: Number,
default: 2,
},
},
data() {
return {
@ -170,6 +174,7 @@ export default {
this.getList()
this.title = `Download Images${this.SubjectCode}${this.Criterion.TrialReadingCriterionName}`
if (this.IsImageSegment) this.title = `Download Images${this.SubjectCode}`
if (this.isReadingTaskViewInOrder === 0) this.title = ''
},
beforeDestroy() {
store.dispatch('trials/setUnLock', false)
@ -447,6 +452,9 @@ export default {
if (this.IsImageSegment) {
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.VisitName}`
}
if (this.isReadingTaskViewInOrder === 0) {
this.model_cfg.title = ''
}
if (item.IsDicom) {
this.modelList = item.DicomStudyList
} else {
@ -488,11 +496,11 @@ export default {
let routeData = null
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true`,
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
})
} else {
routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true`,
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
})
}
this.open = window.open(routeData.href, '_blank')
@ -505,7 +513,7 @@ export default {
var token = getToken()
let trialId = this.$route.query.trialId
const routeData = this.$router.resolve({
path: `/showvisitdicoms?page=download&trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}`,
path: `/showvisitdicoms?page=download&trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
})
this.open = window.open(routeData.href, '_blank')
},

View File

@ -10,7 +10,8 @@
<!--检查列表-->
<el-table :data="list" style="width: 100%" height="300" :loading="loading">
<!--受试者-->
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" sortable />
<el-table-column prop="SubjectCode" :label="$t('upload:dicom:table:subjectCode')" sortable
v-if="isReadingTaskViewInOrder !== 0" />
<!--访视名称-->
<el-table-column prop="VisitName" :label="$t('download:table:VisitName')" v-if="IsImageSegment" sortable />
<!--任务名称-->
@ -553,6 +554,7 @@ export default {
this.openVisitTaskId = item.VisitTaskId
this.model_cfg.title = `${item.SubjectCode || ''} > ${this.IsImageSegment ? item.VisitName : item.TaskBlindName
}`
if (this.isReadingTaskViewInOrder === 0) this.model_cfg.title = ''
this.modelList = item[list]
this.model_cfg.visible = true
},
@ -1642,7 +1644,7 @@ export default {
const routeData = this.$router.resolve({
path: `/showvisitdicoms?page=upload&trialId=${trialId}&visitTaskId=${this.IsImageSegment ? 'undefined' : row.VisitTaskId
}&subjectVisitId=${row.SourceSubjectVisitId
}&isReading=1&TokenKey=${token}&IsReadingTaskViewInOrder=${this.IsReadingTaskViewInOrder}`,
}&isReading=1&TokenKey=${token}&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
})
this.open = window.open(routeData.href, '_blank')
},

View File

@ -11,7 +11,7 @@
<el-tab-pane :label="$t('uploadDicomAndNonedicom:label:nonedicom')" name="nonedicom">
<nonedicomFile v-if="activeName === 'nonedicom'" :SubjectId="SubjectId" :SubjectCode="SubjectCode"
:Criterion="Criterion" :VisitTaskId="VisitTaskId" :isUpload.sync="isUpload" :IsImageSegment="IsImageSegment"
:forbid="forbid" />
:isReadingTaskViewInOrder="isReadingTaskViewInOrder" :forbid="forbid" />
</el-tab-pane>
</el-tabs>
</el-dialog>
@ -70,6 +70,7 @@ export default {
mounted() {
this.title = `Upload Images${this.SubjectCode}${this.Criterion.TrialReadingCriterionName}`
if (this.IsImageSegment) this.title = `Upload Images${this.SubjectCode}`
if (this.isReadingTaskViewInOrder === 0) this.title = ''
store.dispatch('trials/setUnLock', true)
},
methods: {

View File

@ -14,7 +14,8 @@
<el-table :data="list" style="width: 100%" v-adaptive="{ bottomOffset: 60 }" :loading="loading"
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }">
<!--受试者 sortable="custom"-->
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')" />
<el-table-column prop="SubjectCode" :label="$t('upload:nonedicom:table:subject')"
v-if="isReadingTaskViewInOrder !== 0" />
<!--访视名称-->
<el-table-column prop="VisitName" :label="$t('upload:nonedicom:table:VisitName')" sortable
v-if="IsImageSegment" />
@ -265,6 +266,10 @@ export default {
type: Boolean,
default: false,
},
isReadingTaskViewInOrder: {
type: Number,
default: 0,
},
},
data() {
return {
@ -475,7 +480,7 @@ export default {
let trialId = this.$route.query.trialId
var token = getToken()
const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&visitTaskId=${row.VisitTaskId}&TokenKey=${token}`,
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&visitTaskId=${row.VisitTaskId}&TokenKey=${token}&IsReadingTaskViewInOrder=${this.isReadingTaskViewInOrder}`,
})
this.open = window.open(routeData.href, '_blank')
},

View File

@ -7,7 +7,8 @@
</el-button>
<el-table :data="modelList" style="width: 100%" height="300">
<!--检查编号-->
<el-table-column prop="StudyCode" :label="$t('trials:uploadImage:table:StudyCode')" />
<el-table-column prop="StudyCode" :label="$t('trials:uploadImage:table:StudyCode')"
v-if="IsReadingTaskViewInOrder !== 0" />
<!--检查类型-->
<el-table-column prop="ModalityForEdit" :label="$t('trials:uploadImage:table:ModalityForEdit')"
v-if="IsDicom" />
@ -187,11 +188,11 @@ export default {
var token = getToken()
if (!this.IsImageSegment && (this.Criterion.CriterionType == 19 || this.Criterion.CriterionType == 20)) {
routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true`,
path: `/showNoneDicoms?trialId=${trialId}&isImageSegmentLabel=${false}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.IsReadingTaskViewInOrder}`,
})
} else {
routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true`,
path: `/showNoneDicoms?trialId=${trialId}&visitTaskId=${this.visitTaskId}&subjectVisitId=${this.subjectVisitId}&TokenKey=${token}&isReading=true&IsReadingTaskViewInOrder=${this.IsReadingTaskViewInOrder}`,
})
}

View File

@ -377,3 +377,7 @@ body .el-table th.gutter {
vertical-align: -0.4em !important;
cursor: pointer;
}
.mobile_confirm {
width: 200px;
}

View File

@ -20,7 +20,7 @@
:name="`${study.StudyId}`">
<template slot="title">
<div class="collapse-title-wrapper">
<div class="text-desc">
<div class="text-desc" v-if="IsReadingTaskViewInOrder !== 0">
{{ study.StudyCode }}
</div>
<!-- <div v-show="study.Description" class="text-desc">
@ -169,7 +169,7 @@
v-if="study.VisitName === item.VisitName">
<template slot="title">
<div class="collapse-title-wrapper">
<div class="text-desc">
<div class="text-desc" v-if="IsReadingTaskViewInOrder !== 0">
{{ study.StudyCode }}
</div>
<!-- <div v-show="study.Description" class="text-desc">

View File

@ -1,6 +1,6 @@
<template>
<div class="wscn-http404-container">
<div class="wscn-http404" style="display: flex;align-items: center">
<div class="wscn-http404" style="display: flex;align-items: center;flex-wrap: wrap;justify-content: center;">
<div class="pic-404">
<!-- <img class="pic-404__parent" src="@/assets/login-bg.png" alt="404"> -->
<svg-icon icon-class="login-bg" style="width: 100%; height: 100%" />
@ -55,18 +55,20 @@ export default {
position: absolute;
top: 40%;
left: 50%;
width: 100%;
}
.wscn-http404 {
position: relative;
width: 1200px;
width: 100%;
padding: 0 50px;
overflow: hidden;
.pic-404 {
position: relative;
float: left;
width: 500px;
width: 100%;
max-width: 500px;
height: 300px;
overflow: hidden;
margin-right: 10px;
@ -211,6 +213,7 @@ export default {
animation-name: slideUp;
animation-duration: 0.5s;
animation-fill-mode: forwards;
text-align: center;
}
&__headline {

View File

@ -153,7 +153,8 @@ export default {
isAudit: false,
activeNames: [],
Asc: false
Asc: false,
IsReadingTaskViewInOrder: 2
}
},
async created() {
@ -165,6 +166,9 @@ export default {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '')
}
if (this.$router.currentRoute.query.IsReadingTaskViewInOrder) {
this.IsReadingTaskViewInOrder = Number(this.$router.currentRoute.query.IsReadingTaskViewInOrder)
}
this.subjectVisitId = this.$router.currentRoute.query.subjectVisitId
this.studyId = this.$router.currentRoute.query.studyId
this.getNoneDicomList()

View File

@ -25,19 +25,10 @@
<div class="login_content">
<div class="form-label-width">
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
<el-select
v-model="form.TrialSiteId"
filterable
style="width:100%;"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
@change="handleSiteChange"
>
<el-option
v-for="(item,index) of siteOptions"
:key="index"
:label="item.TrialSiteAliasName"
:value="item.TrialSiteId"
/>
<el-select v-model="form.TrialSiteId" filterable style="width:100%;"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" @change="handleSiteChange">
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName"
:value="item.TrialSiteId" />
</el-select>
</el-form-item>
<!-- 中心编号 -->
@ -49,74 +40,149 @@
<el-input v-model="form.UserName" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item>
<!-- 联系电话 -->
<el-form-item
:label="$t('trials:researchForm:form:contactorPhone')"
prop="Phone"
>
<el-form-item :label="$t('trials:researchForm:form:contactorPhone')" prop="Phone">
<el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item>
<!-- 联系邮箱 -->
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')">
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="Email">
<el-input v-model="form.Email" disabled />
</el-form-item>
<el-form-item :label="$t('trials:researchForm:form:CommonUploadRecordId')
" v-if="IsSupportUploadFile" class="file">
<el-input v-model="form.SiteSurveyFile.FileName" type="textarea" :autosize="{ minRows: 1, maxRows: 3 }"
style="margin-right: 5px;" disabled />
<div class="upload" v-if="!(!(state === 0 && userTypeEnumInt === 0) || isHistory)">
<input accept=".pdf,.docx,.doc" type="file" name="uploadFolder" class="select-file" title=""
@change="beginScanFiles($event)" />
<div class="btn-select">
{{ $t('dictionary:template:basicData:button:selectFile') }}
</div>
</div>
<!-- <el-button type="primary" @click="viewManualFile"
:disabled="!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path">{{
$t('trials:researchForm:form:preview') }}</el-button> -->
<el-button type="primary" @click="downLoad"
:disabled="!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path">{{
$t('trials:researchForm:form:download') }}</el-button>
</el-form-item>
<!-- 平均刻盘周期 -->
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')" :label="$t('trials:researchForm:form:engravingCycle')">
<el-input-number v-model="form.AverageEngravingCycle" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0" style="width:100%;" />
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')"
:label="$t('trials:researchForm:form:engravingCycle')">
<el-input-number v-model="form.AverageEngravingCycle"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0"
style="width:100%;" />
</el-form-item>
</div>
<!-- MRI-PDFF 是否为本中心该适应症的常规诊疗检查项目 -->
<el-form-item v-if="!notShowFieldList.includes('IsRoutineMRIPDEE')"
:label="$t('trials:researchForm:form:IsRoutineMRIPDEE')" prop="IsRoutineMRIPDEE">
<el-radio-group v-model="form.IsRoutineMRIPDEE"
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)">
<el-radio v-for="item of $d.YesOrNo" :key="`IsRoutineMRIPDEE${item.value}`" :label="item.value">{{
item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- MRI-PDFF 检查的检测周期含单次检查时长预约等待时长等 -->
<el-form-item
v-if="!notShowFieldList.includes('MRIPDFFScanTime') || !notShowFieldList.includes('MRIPDFFLeadTime') || !notShowFieldList.includes('MRIPDFFOther')"
:label="$t('trials:researchForm:form:IsMRIPDFF')">
</el-form-item>
<!-- 单次检查时长分钟 -->
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFScanTime')"
:label="$t('trials:researchForm:form:MRIPDFFScanTime')">
<el-input-number v-model="form.MRIPDFFScanTime"
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" controls-position="right" :min="0" />
</el-form-item>
<!-- 平均预约等待时长 -->
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFLeadTime')"
:label="$t('trials:researchForm:form:MRIPDFFLeadTime')">
<el-input-number v-model="form.MRIPDFFLeadTime"
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" controls-position="right" :min="0" />
</el-form-item>
<!-- 特殊情况备注-->
<el-form-item v-if="!notShowFieldList.includes('MRIPDFFOther')"
:label="$t('trials:researchForm:form:MRIPDFFOther')">
<el-input v-model="form.MRIPDFFOther" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" />
</el-form-item>
<!-- 如已选择研究者评估项目是否会授权影像科老师参与本试验如不单独授权是否可在试验中保持 1-2 名固定技师操作-->
<el-form-item
v-if="!notShowFieldList.includes('IsAuthorizeRadiologistsParticipate') || !notShowFieldList.includes('AssignFixedTechnologists')"
:label="$t('trials:researchForm:form:IsAuthorize')" prop="IsAuthorize">
<el-radio-group v-model="form.IsAuthorize" :disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)"
@input="handleIsAuthorizeInput">
<el-radio label="IsAuthorizeRadiologistsParticipate">{{
$t('trials:researchForm:form:IsAuthorizeRadiologistsParticipate') }}</el-radio>
<el-radio label="AssignFixedTechnologists">{{
$t('trials:researchForm:form:AssignFixedTechnologists') }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质技师证对应设备的大型设备上岗证 -->
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')" :label="$t('trials:researchForm:form:isQualified')">
<el-radio-group v-model="form.IsConfirmImagingTechnologist" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio
v-for="item of $d.YesOrNo"
:key="`IsConfirmImagingTechnologist${item.value}`"
:label="item.value"
>{{ item.label }}</el-radio>
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')"
:label="$t('trials:researchForm:form:isQualified')" prop="IsConfirmImagingTechnologist">
<el-radio-group v-model="form.IsConfirmImagingTechnologist"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio v-for="item of $d.YesOrNo" :key="`IsConfirmImagingTechnologist${item.value}`"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 原因 -->
<el-form-item
v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false"
:label="$t('trials:researchForm:form:notQualifiedReason')"
>
<el-input
v-model="form.NotConfirmReson"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
/>
:label="$t('trials:researchForm:form:notQualifiedReason')" prop="NotConfirmReson">
<el-input v-model="form.NotConfirmReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item>
<!-- 研究单位疗效评估人员类型 -->
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')" :label="$t('trials:researchForm:form:staffType')">
<el-radio-group v-model="form.EfficacyEvaluatorType" :disabled="!(state === 0 && userTypeEnumInt === 0)|| isHistory">
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`" :label="item.value">{{ item.label }}</el-radio>
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')"
:label="$t('trials:researchForm:form:staffType')">
<el-radio-group v-model="form.EfficacyEvaluatorType"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')">
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')" prop="IsFollowStudyParameters">
<span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" />
<el-radio-group v-model="form.IsFollowStudyParameters" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{ item.label }}</el-radio>
<el-radio-group v-model="form.IsFollowStudyParameters"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{
item.label }}</el-radio>
</el-radio-group>
<el-button type="primary" size="small" style="margin-left: 5px;" @click="viewManual">
{{ $t('trials:researchForm:button:viewManual') }}
</el-button>
</el-form-item>
<!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
<el-form-item
v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
>
<el-form-item v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
prop="NotFollowReson">
<span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" />
<el-input
v-model="form.NotFollowReson"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
/>
<el-input v-model="form.NotFollowReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item>
<!-- 是否严格按照影像手册参数完成刻盘 -->
<el-form-item v-if="!notShowFieldList.includes('ISStrictManualBurnFlag')" prop="ISStrictManualBurnFlag">
<span slot="label" v-html="$t('trials:researchForm:form:ISStrictManualBurnFlag')" />
<el-radio-group v-model="form.ISStrictManualBurnFlag"
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" style="margin-right: 10px;">
<el-radio v-for="item of $d.YesOrNo" :key="`ISStrictManualBurnFlag${item.value}`" :label="item.value">{{
item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<!-- 不能严格按照影像手册参数完成刻盘原因 -->
<el-form-item v-if="!notShowFieldList.includes('NotStrictManualBurnFlagReason') && !form.ISStrictManualBurnFlag"
prop="NotStrictManualBurnFlagReason">
<span slot="label" v-html="$t('trials:researchForm:form:NotStrictManualBurnFlagReason')" />
<el-input v-model="form.NotStrictManualBurnFlagReason" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }"
:disabled="(!(state === 0 && userTypeEnumInt === 0) || isHistory)" />
</el-form-item>
</div>
</el-form>
</div>
</template>
<script>
import { getTrialSiteSelect } from '@/api/trials'
import { getTrialSiteSelect, getTrialDocumentList, addOrUpdateCommonUploadRecord } from '@/api/trials'
import { addOrUpdateTrialSiteSurvey } from '@/api/research'
export default {
name: 'ResearchBasicInfo',
@ -124,7 +190,15 @@ export default {
isHistory: {
type: Boolean,
default: false
}
},
IsOnlyUploadFile: {
type: Boolean,
default: false
},
IsSupportUploadFile: {
type: Boolean,
default: false
},
},
data() {
var checkPhone = (rule, value, callback) => {
@ -156,16 +230,51 @@ export default {
Phone: '', //
Email: '', //
AverageEngravingCycle: '',
IsRoutineMRIPDEE: '',
MRIPDFFScanTime: '',
MRIPDFFLeadTime: '',
MRIPDFFOther: '',
IsAuthorize: '',
IsAuthorizeRadiologistsParticipate: '',
AssignFixedTechnologists: '',
ISStrictManualBurnFlag: '',
NotStrictManualBurnFlagReason: '',
IsConfirmImagingTechnologist: '',
NotConfirmReson: '',
EfficacyEvaluatorType: '',
IsFollowStudyParameters: '',
NotFollowReson: ''
NotFollowReson: '',
CommonUploadRecordId: null,
SiteSurveyFile: []
},
rules: {
TrialSiteId: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
],
IsRoutineMRIPDEE: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
],
IsAuthorize: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
],
ISStrictManualBurnFlag: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
],
IsFollowStudyParameters: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
],
IsConfirmImagingTechnologist: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: 'blur' }
],
NotConfirmReson: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
],
NotFollowReson: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
],
NotStrictManualBurnFlagReason: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: 'blur' }
],
UserName: [
{ required: true, validator: (rule, value, callback) => { !value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback() }, trigger: 'blur' },
{ min: 0, max: 50, message: this.$t('trials:researchForm:formRule:maxLength'), trigger: ['blur', 'change'] }
@ -186,14 +295,173 @@ export default {
state: null,
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
isShow: false,
notShowFieldList: []
notShowFieldList: [],
perview_visible: false,
ExternalList: []
}
},
methods: {
//
handleSave(isAutoCommit) {
return new Promise(async(resolve) => {
async beginScanFiles(e) {
try {
let file = e.target.files[0]
let name = file.name
if (!this.checkFileSuffix(name)) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:checkFileSuffix"))
this.loading = true
file = await this.fileToBlob(file)
let scope = this
var index = name.lastIndexOf('.')
var type = name.substring(index + 1, name.length)
let res = await this.OSSclient.put(
`/${this.$route.query.trialId}/InspectionUpload/SiteSurvey/${this.form.TrialSiteId}/${scope.getGuid(Date.now() + '_' + name.split('.')[0])}.${type}`,
file
)
let data = {
Path: this.$getObjectName(res.url),
FileName: name,
FileSize: file.size,
FileType: type
}
res = await addOrUpdateCommonUploadRecord(data)
this.loading = false
if (res.IsSuccess) {
this.form.CommonUploadRecordId = res.Result
data.Id = res.Result
this.form.SiteSurveyFile = data
}
} catch (err) {
console.log(err)
this.loading = false;
}
},
checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length)
if ('.pdf'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1 && '.docx'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1 && '.doc'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false
} else {
return true
}
},
handleIsAuthorizeInput(label) {
this.form.IsAuthorizeRadiologistsParticipate = false
this.form.AssignFixedTechnologists = false
this.form[label] = true
},
async viewManualFile() {
if (!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path) return this.$message.warning(this.$t("trials:researchForm:message:notFile"))
this.$preview({
path: this.form.SiteSurveyFile.Path,
type: this.form.SiteSurveyFile.FileType,
title: this.form.SiteSurveyFile.Path.FileName,
})
},
async downLoad() {
if (!this.form.SiteSurveyFile || !this.form.SiteSurveyFile.Path) return this.$message.warning(this.$t("trials:researchForm:message:notFile"))
let link = document.createElement('a')
link.href = this.OSSclientConfig.basePath + this.form.SiteSurveyFile.Path;
link.target = '_blank'
link.download = this.form.SiteSurveyFile.FileName
link.style.display = 'none'
document.body.append(link)
link.click()
document.body.removeChild(link)
link = null
},
async viewManual() {
try {
let data = {
PageIndex: 1,
PageSize: 20,
TrialId: this.$route.query.trialId,
IsPublish: true,
FileTypeCode: 4,
IsDeleted: false
}
let res = await getTrialDocumentList(data)
if (res.IsSuccess) {
const { CurrentPageData } = res.Result
if (CurrentPageData.length <= 0) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:noImageManual"))
this.ExternalList = []
CurrentPageData.forEach(item => {
let obj = {
FilePath: item.Path,
FileFormat: 'pdf',
Name: item.Name
}
this.ExternalList.push(obj)
});
// this.perview_visible = true
this.ExternalList.forEach(item => {
let link = document.createElement('a')
link.href = this.OSSclientConfig.basePath + item.FilePath;
link.target = '_blank'
link.download = item.Name
link.style.display = 'none'
document.body.append(link)
link.click()
document.body.removeChild(link)
link = null
})
}
} catch (err) {
console.log(err)
}
},
//
handleSave(isAutoCommit, isCheck = false) {
return new Promise(async (resolve) => {
isCheck = false
try {
if (this.IsOnlyUploadFile && !isCheck) {
if (!this.form.UserName) {
this.$message.warning(this.$t("trials:researchForm:message:notUserName"))
return resolve(false)
}
if (!this.form.Phone) {
this.$message.warning(this.$t("trials:researchForm:message:notPhone"))
return resolve(false)
}
if (!this.form.CommonUploadRecordId) {
this.$message.warning(this.$t("trials:researchForm:message:notCommonUploadRecordId"))
return resolve(false)
}
this.btnLoading = true
const param = {
id: this.form.Id,
trialId: this.$route.query.trialId,
trialSiteId: this.form.TrialSiteId,
userName: this.form.UserName,
phone: this.form.Phone,
email: this.form.Email,
averageEngravingCycle: this.form.AverageEngravingCycle,
IsRoutineMRIPDEE: this.form.IsRoutineMRIPDEE,
MRIPDFFScanTime: this.form.MRIPDFFScanTime,
MRIPDFFLeadTime: this.form.MRIPDFFLeadTime,
MRIPDFFOther: this.form.MRIPDFFOther,
IsAuthorizeRadiologistsParticipate: this.form.IsAuthorizeRadiologistsParticipate,
AssignFixedTechnologists: this.form.AssignFixedTechnologists,
ISStrictManualBurnFlag: this.form.ISStrictManualBurnFlag,
NotStrictManualBurnFlagReason: this.form.NotStrictManualBurnFlagReason,
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
notConfirmReson: this.form.NotConfirmReson,
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
isFollowStudyParameters: this.form.IsFollowStudyParameters,
notFollowReson: this.form.NotFollowReson,
CommonUploadRecordId: this.form.CommonUploadRecordId
}
addOrUpdateTrialSiteSurvey(param).then(res => {
this.btnLoading = false
if (res.IsSuccess && !isAutoCommit) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
resolve(true)
}).catch(() => {
this.btnLoading = false
reject(false)
})
return resolve(true)
}
const valid = await this.$refs['researchBSForm'].validate()
if (valid) {
this.loading = true
@ -205,11 +473,20 @@ export default {
phone: this.form.Phone,
email: this.form.Email,
averageEngravingCycle: this.form.AverageEngravingCycle,
IsRoutineMRIPDEE: this.form.IsRoutineMRIPDEE,
MRIPDFFScanTime: this.form.MRIPDFFScanTime,
MRIPDFFLeadTime: this.form.MRIPDFFLeadTime,
MRIPDFFOther: this.form.MRIPDFFOther,
IsAuthorizeRadiologistsParticipate: this.form.IsAuthorizeRadiologistsParticipate,
AssignFixedTechnologists: this.form.AssignFixedTechnologists,
ISStrictManualBurnFlag: this.form.ISStrictManualBurnFlag,
NotStrictManualBurnFlagReason: this.form.NotStrictManualBurnFlagReason,
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
notConfirmReson: this.form.NotConfirmReson,
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
isFollowStudyParameters: this.form.IsFollowStudyParameters,
notFollowReson: this.form.NotFollowReson
notFollowReson: this.form.NotFollowReson,
CommonUploadRecordId: this.form.CommonUploadRecordId
}
const res = await addOrUpdateTrialSiteSurvey(param)
this.loading = false
@ -232,7 +509,7 @@ export default {
//
async initForm(trialInfo, trialSiteSurvey, notShowFieldList) {
// site
const { Result } = await getTrialSiteSelect(this.$route.query.trialId)
const { Result } = await getTrialSiteSelect(this.$route.query.trialId, { IgnoreDisable: true })
this.siteOptions = Result
this.form.Id = trialSiteSurvey.Id
this.form.Sponsor = trialInfo.Sponsor //
@ -246,7 +523,20 @@ export default {
this.form.UserName = trialSiteSurvey.UserName //
this.form.Phone = trialSiteSurvey.Phone //
this.form.Email = trialSiteSurvey.Email //
this.form.CommonUploadRecordId = trialSiteSurvey.CommonUploadRecordId
this.form.SiteSurveyFile = trialSiteSurvey.SiteSurveyFile || {}
this.form.fileStr = this.form.SiteSurveyFile.FileName
this.form.AverageEngravingCycle = trialSiteSurvey.AverageEngravingCycle
this.form.IsRoutineMRIPDEE = trialSiteSurvey.IsRoutineMRIPDEE
this.form.MRIPDFFScanTime = trialSiteSurvey.MRIPDFFScanTime
this.form.MRIPDFFLeadTime = trialSiteSurvey.MRIPDFFLeadTime
this.form.MRIPDFFOther = trialSiteSurvey.MRIPDFFOther
this.form.IsAuthorizeRadiologistsParticipate = trialSiteSurvey.IsAuthorizeRadiologistsParticipate
this.form.AssignFixedTechnologists = trialSiteSurvey.AssignFixedTechnologists
if (this.form.IsAuthorizeRadiologistsParticipate) this.form.IsAuthorize = 'IsAuthorizeRadiologistsParticipate'
if (this.form.AssignFixedTechnologists) this.form.IsAuthorize = 'AssignFixedTechnologists'
this.form.ISStrictManualBurnFlag = trialSiteSurvey.ISStrictManualBurnFlag
this.form.NotStrictManualBurnFlagReason = trialSiteSurvey.NotStrictManualBurnFlagReason
this.form.IsConfirmImagingTechnologist = trialSiteSurvey.IsConfirmImagingTechnologist
this.form.NotConfirmReson = trialSiteSurvey.NotConfirmReson
this.form.EfficacyEvaluatorType = trialSiteSurvey.EfficacyEvaluatorType
@ -267,39 +557,46 @@ export default {
}
</script>
<style lang="scss" scoped>
.research_bs_content{
.research_bs_content {
.basic_content{
.basic_content {
padding: 0 20px;
background: #fff;
}
.login_content{
.login_content {
padding: 5px 20px;
margin-top: 5px;
background: #fff;
::v-deep .el-form-item {
padding-bottom: 20px;
}
}
.code_content{
display:flex;
.code_content {
display: flex;
flex-direction: row;
justify-content: flex-start;
.el-input{
.el-input {
margin-right: 10px;
}
}
.form-label-width{
::v-deep .el-form-item__label{
.form-label-width {
::v-deep .el-form-item__label {
width: 140px;
}
::v-deep .el-form-item__content{
::v-deep .el-form-item__content {
margin-left: 140px;
}
}
.submit_content{
.submit_content {
margin-top: 20px;
text-align: center;
}
@ -308,10 +605,61 @@ export default {
margin-bottom: 0px;
padding-top: 5px;
border-bottom: 1px solid #f5f7fa;
.el-form-item__content{
.el-form-item__content {
color: #82848a;
}
}
}
.upload {
display: inline-block;
height: 36px;
width: 90px;
padding: 0 10px;
line-height: 23px;
position: relative;
text-decoration: none;
border-radius: 3px;
overflow: hidden;
text-align: center;
background: #428bca;
border-color: #428bca;
color: #fff;
margin-right: 5px;
.select-file {
height: 36px;
width: 90px;
position: absolute;
overflow: hidden;
left: 0;
top: 0;
opacity: 0;
font-size: 0;
}
.btn-select {
//
// width: 70px;
height: 36px;
line-height: 36px;
text-align: center;
cursor: pointer;
border-radius: 24px;
overflow: hidden;
position: absolute;
top: 0;
left: 10px;
pointer-events: none; //pointer-events:none穿
}
}
.file {
::v-deep .el-form-item__content {
display: flex;
align-items: center;
}
}
</style>

View File

@ -1,59 +1,107 @@
<template>
<div
v-loading="loading"
class="equipment_form_content"
>
<el-form
ref="equipmentForm"
:model="form"
:rules="rules"
label-position="left"
>
<div v-loading="loading" class="equipment_form_content">
<el-form ref="equipmentForm" :model="form" :rules="rules" label-position="left">
<!-- 扫描设备 -->
<el-form-item :label="$t('trials:equiptResearch:form:equipment')" prop="EquipmentTypeId">
<el-select
v-model="form.EquipmentTypeId"
style="width:100%"
>
<el-option
v-for="item of $d.SiteSurvey_ScanEquipmentType"
:key="item.id"
:label="item.label"
:value="item.id"
/>
<el-form-item :label="$t('trials:equiptResearch:form:equipment')" prop="EquipmentTypeEnum"
v-if="EquipmentControlFieldList.includes('EquipmentTypeEnum')">
<div style="display: flex;align-items: center;">
<el-select v-model="form.EquipmentTypeEnum" style="width:100%" @change="form.OtherEquipmentType = null">
<el-option v-for="item of $d.SiteSurvey_ScanEquipmentType" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
<el-input placeholder="" v-model="form.OtherEquipmentType" style="margin-left: 10px;"
v-if="form.EquipmentTypeEnum == '-1'" clearable>
</el-input>
</div>
</el-form-item>
<!-- 扫描参数 -->
<el-form-item v-if="isShowParameters" :label="$t('trials:equiptResearch:form:param')">
<el-form-item :label="$t('trials:equiptResearch:form:param')"
v-if="EquipmentControlFieldList.includes('Parameters')" prop="Parameters">
<el-input v-model="form.Parameters" />
</el-form-item>
<!-- 扫描仪器制造商名称 -->
<el-form-item :label="$t('trials:equiptResearch:form:manufacturer')">
<el-input v-model="form.ManufacturerName" />
<el-form-item :label="$t('trials:equiptResearch:form:manufacturer')"
v-if="EquipmentControlFieldList.includes('ManufacturerType')" prop="ManufacturerType">
<div style="display: flex;align-items: center;">
<el-select v-model="form.ManufacturerType" style="width:100%" @change="form.ManufacturerName = null">
<el-option v-for="item of $d.ManufacturerType" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
<el-input placeholder="" v-model="form.ManufacturerName" style="margin-left: 10px;"
v-if="form.ManufacturerType == '-1'" clearable>
</el-input>
</div>
</el-form-item>
<!-- 扫描仪型号 -->
<el-form-item :label="$t('trials:equiptResearch:form:model')">
<el-form-item :label="$t('trials:equiptResearch:form:model')"
v-if="EquipmentControlFieldList.includes('ScannerType')" prop="ScannerType">
<el-input v-model="form.ScannerType" />
</el-form-item>
<!-- 磁场强度 -->
<el-form-item :label="$t('trials:equiptResearch:form:MagneticFieldStrengthType')"
v-if="EquipmentControlFieldList.includes('MagneticFieldStrengthType')" prop="MagneticFieldStrengthType">
<el-select v-model="form.MagneticFieldStrengthType" style="width:100%">
<el-option v-for="item of $d.MagneticFieldStrengthType" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<!-- 体部线圈通道数 -->
<el-form-item :label="$t('trials:equiptResearch:form:BodyCoilChannelCount')"
v-if="EquipmentControlFieldList.includes('BodyCoilChannelCount')" prop="BodyCoilChannelCount">
<el-select v-model="form.BodyCoilChannelCount" style="width:100%">
<el-option v-for="item of $d.BodyCoilChannelCount" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 是否具备专用的PDFF脂肪定量序列CSE-MRI序列 -->
<el-form-item :label="$t('trials:equiptResearch:form:HasDedicatedPdfFatQuantificationSequence')"
v-if="EquipmentControlFieldList.includes('HasDedicatedPdfFatQuantificationSequence')"
prop="HasDedicatedPdfFatQuantificationSequence">
<el-select v-model="form.HasDedicatedPdfFatQuantificationSequence" style="width:100%"
@change="form.PdfFatQuantificationSequenceType = null, form.OtherSequenceSpecification = null">
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- PDFF脂肪定量序列 -->
<el-form-item :label="$t('trials:equiptResearch:form:PdfFatQuantificationSequenceType')"
prop="PdfFatQuantificationSequenceType"
v-if="form.HasDedicatedPdfFatQuantificationSequence && EquipmentControlFieldList.includes('PdfFatQuantificationSequenceType')">
<div style="display: flex;align-items: center;">
<el-select v-model="form.PdfFatQuantificationSequenceType" style="width:100%"
@change="form.OtherSequenceSpecification = null">
<el-option v-for="item of $d.PdfFatQuantificationSequenceType" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
<el-input placeholder="" v-model="form.OtherSequenceSpecification" style="margin-left: 10px;"
v-if="form.PdfFatQuantificationSequenceType == '-1'" clearable>
</el-input>
</div>
</el-form-item>
<!-- 是否包含 T2/R2 校正用于铁沉积校正 -->
<el-form-item :label="$t('trials:equiptResearch:form:HasT2R2Correction')" prop="HasT2R2Correction"
v-if="EquipmentControlFieldList.includes('HasT2R2Correction')">
<el-select v-model="form.HasT2R2Correction" style="width:100%">
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 是否可完整导出 PDFF 参数图及全部原始 DICOM 数据 -->
<el-form-item :label="$t('trials:equiptResearch:form:CanFullyExportPdfParameterMapsAndRawDicom')"
prop="CanFullyExportPdfParameterMapsAndRawDicom"
v-if="EquipmentControlFieldList.includes('CanFullyExportPdfParameterMapsAndRawDicom')">
<el-select v-model="form.CanFullyExportPdfParameterMapsAndRawDicom" style="width:100%">
<el-option v-for="item of $d.YesOrNo" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 备注 -->
<el-form-item :label="$t('trials:equiptResearch:form:remark')">
<el-form-item :label="$t('trials:equiptResearch:form:remark')" prop="Note"
v-if="EquipmentControlFieldList.includes('Note')">
<el-input v-model="form.Note" />
</el-form-item>
<div style="text-align: center;padding:20px 0px;">
<!-- 取消 -->
<el-button
size="large"
type="primary"
@click="handleCancel"
>
<el-button size="large" type="primary" @click="handleCancel">
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button
size="large"
type="primary"
@click="handleSave"
>
<el-button size="large" type="primary" @click="handleSave">
{{ $t("common:button:save") }}
</el-button>
</div>
@ -76,29 +124,96 @@ export default {
type: String,
default: ''
},
isShowParameters: {
type: Boolean,
default: false
EquipmentControlFieldList: {
type: Array,
default: () => {
return []
}
}
},
data() {
return {
form: {
Id: '',
EquipmentTypeId: '',
Parameters: '',
ManufacturerName: '',
ScannerType: '',
Note: '',
EquipmentTypeEnum: null,
OtherEquipmentType: null,
Parameters: null,
Note: null,
ManufacturerType: null,
ManufacturerName: null,
ScannerType: null,
MagneticFieldStrengthType: null,
BodyCoilChannelCount: null,
HasDedicatedPdfFatQuantificationSequence: null,
PdfFatQuantificationSequenceType: null,
OtherSequenceSpecification: null,
HasT2R2Correction: null,
CanFullyExportPdfParameterMapsAndRawDicom: null,
TrialSiteSurveyId: ''
},
rules: {
EquipmentTypeId: [
EquipmentTypeEnum: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
{
validator: (rule, value, callback) => {
if (this.form.EquipmentTypeEnum === -1 && !this.form.OtherEquipmentType) {
callback(this.$t('common:ruleMessage:specify'));
} else {
callback()
}
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
},
],
Parameters: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
],
// Note: [
// { required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
// ],
ManufacturerType: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
{
validator: (rule, value, callback) => {
if (this.form.ManufacturerType === -1 && !this.form.ManufacturerName) {
callback(this.$t('common:ruleMessage:specify'));
} else {
callback()
}
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
},
],
ScannerType: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change'] }
],
MagneticFieldStrengthType: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
]
],
BodyCoilChannelCount: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
],
HasDedicatedPdfFatQuantificationSequence: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
],
PdfFatQuantificationSequenceType: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] },
{
validator: (rule, value, callback) => {
if (this.form.PdfFatQuantificationSequenceType === -1 && !this.form.OtherSequenceSpecification) {
callback(this.$t('common:ruleMessage:specify'));
} else {
callback()
}
}, message: this.$t('common:ruleMessage:specify'), trigger: ['blur', 'change']
},
],
HasT2R2Correction: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
],
CanFullyExportPdfParameterMapsAndRawDicom: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
],
},
loading: false,
dictionaryList: {}
}
},
mounted() {
@ -154,13 +269,15 @@ export default {
}
</script>
<style lang="scss" scoped>
.equipment_form_content{
.equipment_form_content {
padding: 0 10px;
::v-deep .el-form-item {
margin-bottom: 0px;
padding: 5px 0 20px 0;
border-bottom: 1px solid #f5f7fa;
.el-form-item__content{
.el-form-item__content {
color: #82848a;
}
}

View File

@ -13,18 +13,22 @@
<i class="el-icon-receiving" />
</div>
<div class="p_info">
<div
class="p_info_basic"
:style="{maxWidth:w+'px','white-space': 'nowrap',
<div class="p_info_basic" :style="{
maxWidth: w + 'px', 'white-space': 'nowrap',
overflow: 'hidden',
'text-overflow': 'ellipsis'}"
>
<div class="p_text">{{ item.EquipmentType }}</div>
<div v-if="isShowParameters" class="p_text" style="margin-left:10px">{{ item.Parameters }}</div>
<div class="p_text" style="margin-left:10px">{{ item.ManufacturerName }}</div>
'text-overflow': 'ellipsis'
}">
<div class="p_text" v-if="EquipmentControlFieldList.includes('EquipmentTypeEnum')">
{{ item.OtherEquipmentType ? item.OtherEquipmentType :
$fd('SiteSurvey_ScanEquipmentType', item.EquipmentTypeEnum) }}</div>
<div v-if="EquipmentControlFieldList.includes('Parameters')" class="p_text" style="margin-left:10px">{{
item.Parameters }}</div>
<div class="p_text" style="margin-left:10px" v-if="EquipmentControlFieldList.includes('ManufacturerType')">{{
item.ManufacturerName ? item.ManufacturerName : $fd('ManufacturerType',
item.ManufacturerType) }}</div>
</div>
<div class="p_text">{{ item.ScannerType }}</div>
<div class="p_text">{{ item.Note }}</div>
<div class="p_text" v-if="EquipmentControlFieldList.includes('ScannerType')">{{ item.ScannerType }}</div>
<div class="p_text" v-if="EquipmentControlFieldList.includes('Note')">{{ item.Note }}</div>
</div>
<div v-if="state === 0 && userTypeEnumInt === 0 && !isHistory" class="p_func">
<el-button type="text" @click="handleEdit(item)">
@ -36,19 +40,9 @@
</div>
</div>
<!-- 添加/编辑设备信息 -->
<el-drawer
:title="title"
:visible.sync="formVisible"
direction="btt"
size="70%"
>
<EquipmentForm
v-if="formVisible"
:equipment-info="equipmentInfo"
:is-show-parameters="isShowParameters"
@getList="getList"
@close="close"
/>
<el-drawer :title="title" :visible.sync="formVisible" direction="btt" size="70%">
<EquipmentForm v-if="formVisible" :equipment-info="equipmentInfo"
:EquipmentControlFieldList="EquipmentControlFieldList" @getList="getList" @close="close" />
</el-drawer>
</div>
</template>
@ -81,7 +75,7 @@ export default {
state: null,
trialSiteSurveyId: '',
trialId: '',
isShowParameters: false
EquipmentControlFieldList: []
}
},
mounted() {
@ -142,8 +136,11 @@ export default {
console.log(e)
}
},
initList(TrialSiteEquipmentSurveyList, trialSiteSurvey, isShowParameters) {
this.isShowParameters = isShowParameters
initList(TrialSiteEquipmentSurveyList, trialSiteSurvey, EquipmentControlFieldList) {
this.EquipmentControlFieldList = []
EquipmentControlFieldList.forEach(item => {
this.EquipmentControlFieldList.push(item.FiledName)
})
this.list = TrialSiteEquipmentSurveyList
this.state = trialSiteSurvey.State
this.$forceUpdate()
@ -157,37 +154,42 @@ export default {
}
</script>
<style lang="scss" scoped>
.equipments_content{
.equipments_content {
background: #fff;
padding: 10px;
.title{
.title {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.equipment_info{
.equipment_info {
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
border-top: 1px solid #f5f7fa;
.p_icon{
.p_icon {
width: 70px;
font-size: 25px;
font-weight: bold;
text-align: center;
}
.p_info{
.p_info {
position: relative;
flex:1;
flex: 1;
display: flex;
flex-direction: column;
justify-content: space-evenly;
// border-right: 1px solid #f5f7fa;
font-size: 13px;
}
.p_info:after {
content: '';
position: absolute;
@ -198,22 +200,24 @@ export default {
width: 1px;
background-color: #f5f7fa;
}
.p_info_basic{
.p_info_basic {
display: flex;
flex-direction: row;
align-items: center;
}
.p_text{
.p_text {
line-height: 25px;
color: #82848a;
}
.p_func{
.p_func {
width: 80px;
padding: 0 10px;
text-align: center;
}
}
}
</style>

View File

@ -4,30 +4,22 @@
<div class="d_content">
<!-- 项目基本信息 -->
<BasicInfo ref="basicInfo" />
<BasicInfo ref="basicInfo" :IsOnlyUploadFile="IsOnlyUploadFile" :IsSupportUploadFile="IsSupportUploadFile" />
<!-- 历史人员 -->
<HistoricalParticipants ref="historicalParticipant" class="mt5" />
<!-- 新增人员 -->
<Participants ref="participants" class="mt5" />
<!-- 设备调研 -->
<Equipments ref="equipments" class="mt5" />
<Equipments ref="equipments" class="mt5" v-if="!siteSurveyNoteInfo.IsCloseEquipmentSurvey" />
<!-- 备注 -->
<Notes ref="notes" class="mt5" />
</div>
<div class="d_footer">
<div class="d_func_row">
<div
v-if="state === 0 && userTypeEnumInt === 0"
class="d_func"
@click="handleSave"
>
<div v-if="state === 0 && userTypeEnumInt === 0" class="d_func" @click="handleSave">
{{ $t('common:button:save') }}
</div>
<div
v-if="(state === 0 && userTypeEnumInt === 0)"
class="d_func"
@click="handleSubmit('submit')"
>
<div v-if="(state === 0 && userTypeEnumInt === 0)" class="d_func" @click="handleSubmit('submit')">
{{ $t('trials:researchForm:button:submit') }}
</div>
</div>
@ -58,7 +50,9 @@ export default {
userTypeEnumInt: 0,
rejectVisible: false,
rejectForm: { reason: '' },
siteSurveyNoteInfo: null
siteSurveyNoteInfo: {},
IsSupportUploadFile: false,
IsOnlyUploadFile: false
}
},
mounted() {
@ -78,6 +72,9 @@ export default {
if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) {
this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote')
}
this.IsSupportUploadFile = res.Result.SiteSurveyFiledConfig.IsSupportUploadFile
this.IsOnlyUploadFile = res.Result.SiteSurveyFiledConfig.IsOnlyUploadFile
this.siteSurveyNoteInfo.IsCloseEquipmentSurvey = res.Result.SiteSurveyFiledConfig.IsCloseEquipmentSurvey
this.state = res.Result.TrialSiteSurvey.State
this.$refs['basicInfo'].initForm(res.Result.TrialInfo, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig ? res.Result.SiteSurveyFiledConfig.NotShowFieldList : null)
var historicalArr = []
@ -92,7 +89,7 @@ export default {
this.$refs['historicalParticipant'].initList(historicalArr, res.Result.TrialSiteSurvey)
this.$refs['participants'].initList(newArr, res.Result.TrialSiteSurvey)
this.$refs['equipments'].initList(res.Result.TrialSiteEquipmentSurveyList, res.Result.TrialSiteSurvey, !(res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0))
this.$refs['equipments'].initList(res.Result.TrialSiteEquipmentSurveyList, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig.EquipmentControlFieldList)
this.$refs['notes'].initPage(this.siteSurveyNoteInfo)
}
this.loading = false
@ -129,7 +126,8 @@ export default {
this.userTypeEnumInt === 0 ? this.$t('trials:researchForm:message:submitWarning') : this.$t('trials:researchForm:message:submitWarning2'),
{
type: 'warning',
distinguishCancelAndClose: true
distinguishCancelAndClose: true,
customClass: "mobile_confirm"
}
)
if (confirm !== 'confirm') return
@ -160,9 +158,10 @@ export default {
}
</script>
<style lang="scss" scoped>
.research_detal_wrapper{
background-color:#f5f7fa;
.d_title{
.research_detal_wrapper {
background-color: #f5f7fa;
.d_title {
margin-bottom: 5px;
line-height: 80px;
font-size: 28px;
@ -173,10 +172,11 @@ export default {
top: 0;
z-index: 10;
}
// .d_content{
// }
.d_footer{
.d_footer {
position: sticky;
bottom: 0;
z-index: 10;
@ -185,12 +185,14 @@ export default {
text-align: center;
// padding: 20px;
}
.d_func_row{
.d_func_row {
display: flex;
flex-direction: row;
justify-content: space-between;
}
.d_func{
.d_func {
flex: 1;
margin: 20px;
color: #fff;
@ -207,15 +209,16 @@ export default {
line-height: 1;
white-space: nowrap;
cursor: pointer;
&:hover{
&:hover {
background: #68a2d5;
border-color: #68a2d5;
color: #fff;
}
}
.mt5{
.mt5 {
margin-top: 5px
}
}
</style>

View File

@ -1,131 +1,88 @@
<template>
<div class="research_login_m_content">
<div class="title">{{ $t('trials:researchForm:title:question') }}</div>
<el-form
ref="loginForm"
v-loading="loading"
label-position="left"
label-width="120px"
:model="form"
:rules="rules"
>
<div v-if="IsExpired"></div>
<div v-else-if="verify" class="LinkVerificationCode_content">
<el-form ref="codeForm" v-loading="loading" label-position="top" label-width="120px" :model="codeForm"
:rules="code_rules">
<div class="basic_content">
<!-- 项目编号 -->
<el-form-item
:label="$t('trials:researchForm:form:trialId')"
>
<el-form-item :label="$t('trials:researchForm:message:LinkVerificationCode')" prop="LinkVerificationCode">
<el-input v-model="codeForm.LinkVerificationCode" autocomplete="new-password" />
</el-form-item>
</div>
</el-form>
<div class="submit_content">
<el-button size="large" type="primary" @click="getLinkVerificationCodeIsEffective">
{{ $t('common:button:submit') }}
</el-button>
</div>
</div>
<template v-else>
<div class="title">{{ $t('trials:researchForm:title:question') }}</div>
<el-form ref="loginForm" v-loading="loading" label-position="left" label-width="120px" :model="form"
:rules="rules">
<div class="basic_content">
<!-- 项目编号 -->
<el-form-item :label="$t('trials:researchForm:form:trialId')">
<span>{{ form.TrialCode }}</span>
</el-form-item>
<!-- 试验方案号 -->
<el-form-item
:label="$t('trials:researchForm:form:researchNo')"
>
<el-form-item :label="$t('trials:researchForm:form:researchNo')">
<span>{{ form.ResearchProgramNo }}</span>
</el-form-item>
<!-- 试验名称 -->
<el-form-item
:label="$t('trials:researchForm:form:researchName')"
>
<el-form-item :label="$t('trials:researchForm:form:researchName')">
<span>{{ form.ExperimentName }}</span>
</el-form-item>
<!-- 适应症类型 -->
<el-form-item
:label="$t('trials:researchForm:form:decleareType')"
>
<el-form-item :label="$t('trials:researchForm:form:decleareType')">
<span>{{ form.IndicationType }}</span>
</el-form-item>
</div>
<div class="login_content">
<el-form-item
:label="$t('trials:researchForm:form:siteName')"
prop="TrialSiteId"
>
<el-select
v-model="form.TrialSiteId"
filterable
style="width:100%;"
@change="handleSiteChange"
>
<el-option
v-for="(item,index) of siteOptions"
:key="index"
:label="item.TrialSiteAliasName"
:value="item.TrialSiteId"
/>
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
<el-select v-model="form.TrialSiteId" filterable style="width:100%;" @change="handleSiteChange">
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName"
:value="item.TrialSiteId" />
</el-select>
</el-form-item>
<el-form-item
v-if="form.TrialSiteId && isHaveSiteSurveyRecord"
label=""
style="text-align:right;"
>
<el-form-item v-if="form.TrialSiteId && isHaveSiteSurveyRecord" label="" style="text-align:right;">
<!-- 更新调研表 -->
<el-link
v-if="!form.IsUpdate"
type="primary"
@click="form.IsUpdate = true"
>
<el-link v-if="!form.IsUpdate" type="primary" @click="form.IsUpdate = true">
{{ $t('trials:researchForm:button:updateQsForm') }}
</el-link>
<!-- 取消更新调研表 -->
<el-link
v-else
type="primary"
@click="form.IsUpdate = false;form.ReplaceUserEmailOrPhone=''"
>
<el-link v-else type="primary" @click="form.IsUpdate = false; form.ReplaceUserEmailOrPhone = ''">
{{ $t('trials:researchForm:button:cancelUpdateQsForm') }}
</el-link>
</el-form-item>
<!-- 原调研表填写人邮箱 -->
<el-form-item
v-if="form.IsUpdate"
:label="$t('trials:researchForm:form:originalEmail')"
prop="ReplaceUserEmailOrPhone"
>
<el-input
v-model="form.ReplaceUserEmailOrPhone"
autocomplete="new-password"
/>
<el-form-item v-if="form.IsUpdate" :label="$t('trials:researchForm:form:originalEmail')"
prop="ReplaceUserEmailOrPhone">
<el-input v-model="form.ReplaceUserEmailOrPhone" autocomplete="new-password" />
</el-form-item>
<!-- 联系邮箱 -->
<el-form-item
:label="$t('trials:researchForm:form:contactorEmail')"
prop="EmailOrPhone"
>
<el-input
v-model="form.EmailOrPhone"
autocomplete="new-password"
/>
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="EmailOrPhone">
<el-input v-model="form.EmailOrPhone" autocomplete="new-password" />
</el-form-item>
<el-form-item
:label="$t('trials:researchForm:form:verifyCode')"
>
<el-form-item :label="$t('trials:researchForm:form:verifyCode')">
<div class="code_content">
<el-input
v-model="form.VerificationCode"
autocomplete="new-password"
/>
<el-button
type="primary"
:disabled="sendDisabled || !form.EmailOrPhone || count > 0"
@click="handleSendCode"
>
<el-input v-model="form.VerificationCode" autocomplete="new-password" />
<el-button type="primary" :disabled="sendDisabled || !form.EmailOrPhone || count > 0"
@click="handleSendCode">
{{ this.$t('trials:researchForm:button:send') }} {{ sendTitle ? `${sendTitle}` : null }}
</el-button>
</div>
</el-form-item>
<div class="submit_content">
<el-button
size="large"
type="primary"
@click="onSubmit"
>
<el-button size="large" type="primary" @click="onSubmit">
{{ $t('common:button:submit') }}
</el-button>
</div>
</div>
</el-form>
</template>
</div>
</template>
<script>
@ -133,6 +90,10 @@ import { sendVerifyCode, verifySendCode, getTrialSurveyInitInfo } from '@/api/re
import { getUserMenuTree, getUserPermissions } from '@/api/user'
import store from '@/store'
import { mapGetters, mapMutations } from 'vuex'
import {
getLinkLinkExpirationTime,
getLinkVerificationCodeIsEffective
} from '@/api/trials'
export default {
name: 'ResearchMobileLogin',
data() {
@ -185,6 +146,16 @@ export default {
}
return {
trialId: '',
IsExpired: true,
verify: true,
codeForm: {
LinkVerificationCode: null,
},
code_rules: {
LinkVerificationCode: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: ['blur'] }
],
},
form: {
Sponsor: null, //
ResearchProgramNo: null, //
@ -239,16 +210,119 @@ export default {
])
},
mounted() {
this.$i18n.locale = this.$route.query.lang
this.setLanguage(this.$route.query.lang)
let lang = this.$route.query.lang
if (!lang) {
const language = navigator.language
lang = 'en'
if (language.includes("zh")) {
lang = 'zh'
}
}
this.$i18n.locale = lang
this.setLanguage(lang)
this.$updateDictionary()
this.getLinkTimeIsExpired()
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
async getLinkTimeIsExpired() {
try {
let data = {
TrialId: this.$route.query.trialId,
}
let res = await getLinkLinkExpirationTime(data)
if (res.IsSuccess) {
if (res.Result.IsExpired) {
return this.$router.replace('/link_expired')
// return this.$confirm(this.$t("trials:researchForm:confirm:linkIsExpired"), '', {
// type: 'warning'
// })
// return this.IsExpired = true
}
// this.customPrompt()
this.IsExpired = false
}
} catch (err) {
console.log(err)
}
},
async getLinkVerificationCodeIsEffective() {
try {
let validate = await this.$refs.codeForm.validate()
if (!validate) return false
let data = {
TrialId: this.$route.query.trialId,
LinkVerificationCode: this.codeForm.LinkVerificationCode
}
let res = await getLinkVerificationCodeIsEffective(data)
if (res.IsSuccess) {
if (!res.Result.IsEffective) {
return false
}
this.verify = false
if (this.$route.query.trialId) {
this.trialId = this.$route.query.trialId
this.initPage()
}
if (this.$route.query.isUpload) {
this.isUpload = true
this.form.IsUpdate = true
let { email, oldEMail, trialSiteId } = this.$route.query
if (trialSiteId) this.form.TrialSiteId = trialSiteId
if (oldEMail) this.form.ReplaceUserEmailOrPhone = oldEMail
if (email && email !== 'null') {
this.form.EmailOrPhone = email
} else {
this.form.EmailOrPhone = oldEMail
}
if ((email && email !== 'null') || (oldEMail && oldEMail !== 'null')) {
this.isNeedUpload = false
}
}
}
return true
} catch (err) {
return false
console.log(err)
}
},
async customPrompt(name) {
try {
const that = this
//
let message = this.$t('trials:researchForm:message:LinkVerificationCode')
const { value } = await this.$prompt(message, '', {
showClose: false,
cancelButtonText: this.$t('common:button:cancel'),
confirmButtonText: this.$t('trials:researchForm:button:saveLinkCode'),
showCancelButton: false,
closeOnClickModal: false,
closeOnPressEscape: false,
inputValue: name,
beforeClose: async (action, instance, done) => {
if (action === 'confirm') {
const value = instance.inputValue
if (!value) {
that.$message.error(this.$t('trials:researchForm:error:noValue'))
} else {
let flag = await this.getLinkVerificationCodeIsEffective(value)
if (!flag) {
that.$message.error(this.$t('trials:researchForm:confirm:isEffective'))
} else {
done()
}
}
} else {
done()
}
}
})
this.getLinkVerificationCodeIsEffective(value)
} catch (err) {
console.log(err)
return null
}
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
//
async initPage() {
try {
@ -292,8 +366,18 @@ export default {
if (res.IsSuccess) {
zzSessionStorage.clear()
this.$i18n.locale = this.$route.query.lang
this.setLanguage(this.$route.query.lang)
// this.$i18n.locale = this.$route.query.lang
// this.setLanguage(this.$route.query.lang)
let lang = this.$route.query.lang
if (!lang) {
const language = navigator.language
lang = 'en'
if (language.includes("zh")) {
lang = 'zh'
}
}
this.$i18n.locale = lang
this.setLanguage(lang)
store.dispatch('user/setToken', res.Result.Token)
zzSessionStorage.setItem('TokenKey', res.Result.Token)
var permissions = await getUserPermissions()
@ -363,9 +447,10 @@ export default {
}
</script>
<style lang="scss" scoped>
.research_login_m_content{
background-color:#f5f7fa;
.title{
.research_login_m_content {
background-color: #f5f7fa;
.title {
margin-bottom: 5px;
line-height: 80px;
font-size: 28px;
@ -373,27 +458,33 @@ export default {
text-align: center;
background: #fff;
}
.basic_content{
.basic_content {
padding: 0 20px;
background: #fff;
}
.login_content{
.login_content {
padding: 5px 20px;
margin-top: 5px;
background: #fff;
::v-deep .el-form-item {
padding-bottom: 20px;
}
}
.code_content{
display:flex;
.code_content {
display: flex;
flex-direction: row;
justify-content: flex-start;
.el-input{
.el-input {
margin-right: 10px;
}
}
.submit_content{
.submit_content {
margin-top: 20px;
text-align: center;
}
@ -402,11 +493,20 @@ export default {
margin-bottom: 0px;
padding-top: 5px;
border-bottom: 1px solid #f5f7fa;
.el-form-item__content{
.el-form-item__content {
color: #82848a;
}
}
}
.LinkVerificationCode_content {
position: fixed;
top: 40%;
bottom: 40%;
right: 0;
left: 0;
}
</style>

View File

@ -412,6 +412,7 @@ export default {
//
handleSave(isAutoCommit, isCheck = false) {
return new Promise((resolve, reject) => {
isCheck = false
if (this.IsOnlyUploadFile && !isCheck) {
if (!this.form.UserName) {
this.$message.warning(this.$t("trials:researchForm:message:notUserName"))

View File

@ -191,7 +191,6 @@ export default {
EquipmentControlFieldList.forEach(item => {
this.EquipmentControlFieldList.push(item.FiledName)
})
console.log(this.EquipmentControlFieldList, 'this.EquipmentControlFieldList')
this.list = TrialSiteEquipmentSurveyList
this.state = trialSiteSurvey.State
this.$forceUpdate()

View File

@ -154,8 +154,8 @@ import NoticeForm from './components/from'
import Pagination from '@/components/Pagination'
const searchDataDefault = () => {
return {
Asc: true,
SortField: '',
Asc: false,
SortField: 'PublishedTime',
NoticeContent: null,
FileName: null,
NoticeTypeEnum: null,

View File

@ -388,7 +388,7 @@ export default {
this.shareLoading = false
if (res.IsSuccess) {
this.validityPeriod = res.Result.LinkExpirationTime
this.LinkVerificationCode = res.Result.LinkVerificationCode || this.$route.query.researchProgramNo
this.LinkVerificationCode = res.Result.LinkVerificationCode || res.Result.ResearchProgramNo
if (!this.validityPeriod) {
this.LinkVerificationCode = null
}

View File

@ -27,7 +27,7 @@
class="study-wrapper">
<StudyList v-if="selectArr.includes(s.VisitTaskId)" :ref="s.VisitTaskId" :visit-task-id="s.VisitTaskId"
:trial-id="trialId" :subject-visit-id="s.VisitId" :task-blind-name="s.TaskBlindName"
:is-reading-show-subject-info="isReadingShowSubjectInfo" @loadImageStack="loadImageStack"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :is-reading-task-view-in-order="isReadingTaskViewInOrder" @loadImageStack="loadImageStack"
@previewNoneDicoms="previewNoneDicoms" />
</div>
</div>

View File

@ -505,15 +505,23 @@ export default {
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 (this.CriterionType === 22) {
idx = item.Childrens.findIndex(i => i.QuestionMark === 1106)
}
if (idx > -1) {
if (item.Childrens[idx].Answer.length > 0) {
var k = item.Childrens[idx].Answer.findIndex(v => v.Answer !== '')
var part = ''
if (this.CriterionType === 22) {
part = item.Childrens[idx].Answer[k].Answer ? this.$fd('Liver4Segmentation', parseInt(item.Childrens[idx].Answer[k].Answer)) : ''
} else {
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}`
@ -531,6 +539,7 @@ export default {
this.$set(obj, 'Answers', Answers)
// obj.QuestionName = `${obj.QuestionName} `
} else if (!item.SplitOrMergeLesionName && k > -1) {
console.log(part)
obj.QuestionName = `${obj.QuestionName}--${part}`
const Answers = {}
if (state >= 0) {

View File

@ -28,7 +28,7 @@
</div>
<div>
<span class="study-meta-line" :title="study.Modalities">
<span class="study-code" :title="study.StudyCode">{{ study.StudyCode }}</span>
<span v-if="isReadingTaskViewInOrder !== 0" class="study-code" :title="study.StudyCode">{{ study.StudyCode }}</span>
<span class="study-modality">{{ study.Modalities }}({{ study.SeriesCount }})</span>
<span class="patient-info" v-if="['PT、CT', 'CT、PT', 'PET-CT'].includes(study.Modalities)">
<el-popover placement="right-start" trigger="hover" popper-class="patient-info-popper">
@ -226,6 +226,10 @@ export default {
isReadingShowSubjectInfo: {
type: Boolean,
required: true
},
isReadingTaskViewInOrder: {
type: Number,
required: true
}
},
data() {
@ -340,7 +344,7 @@ export default {
}
})
var i = -1
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
var isReadingTaskViewInOrder = parseInt(this.isReadingTaskViewInOrder)
if (isReadingTaskViewInOrder === 2) {
//
i = res.length === 2 ? 1 : -1
@ -427,7 +431,7 @@ export default {
async getInitSeries() {
var seriesList = []
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
var isReadingTaskViewInOrder = parseInt(this.isReadingTaskViewInOrder)
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
this.studyList = this.visitTaskList[idx].StudyList
const studyList = this.visitTaskList[idx].StudyList.filter(i => i.IsDicom)

View File

@ -585,7 +585,7 @@
:visit-task-id="taskId" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
<download-dicom-and-nonedicom v-if="downloadImageVisible" :subject-id="uploadSubjectId"
:subject-code="uploadSubjectCode" :criterion="uploadTrialCriterion" :task-id="taskId"
:visible.sync="downloadImageVisible" />
:visible.sync="downloadImageVisible" :is-reading-task-view-in-order="isReadingTaskViewInOrder" />
<readingChart ref="readingChart" />
</div>
</template>

View File

@ -40,9 +40,9 @@
@click.prevent="setToolActive('CircularEraser')">
<svg-icon icon-class="clear" class="svg-icon" />
</div>
<div :class="['tool-item']">
<!-- <div :class="['tool-item']">
<input type="file" @change="beginScanFiles($event)">
</div>
</div> -->
</div>
<div class="ConfigBox">
<div class="EraserConfig"
@ -133,8 +133,8 @@
</div>
<div class="SegmentConfig">
<span>{{ $t('trials:reading:Segmentations:title:Border') }}</span>
<el-slider v-model="SegmentConfig.outlineWidth" show-input :step="1" :max="10"
input-size="mini" :show-input-controls="false" />
<el-slider v-model="SegmentConfig.outlineWidth" show-input :step="1" :max="10" input-size="mini"
:show-input-controls="false" />
</div>
<span class="line" />
<div class="SegmentConfig" style="justify-content: flex-start;">
@ -602,6 +602,7 @@ export default {
brushSize: {
handler() {
this.setBrushSize(this.activeTool)
this.setSegmentConfig()
},
deep: true
},

View File

@ -4,7 +4,10 @@
<div v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo" :title="taskInfo.SubjectCode">
{{ taskInfo.SubjectCode }}
</div>
<div v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo" :title="visitTaskInfo.TaskBlindName">
<div :title="visitTaskInfo.TaskBlindName">
<span v-if="taskInfo && !taskInfo.IsReadingShowSubjectInfo">
{{ $t('trials:reading:title:taskName') }}
</span>
{{ visitTaskInfo.TaskBlindName }}
</div>
</div>
@ -21,7 +24,7 @@
</div>
<div>
<span class="study-meta-line" :title="study.Modalities">
<span class="study-code" :title="study.StudyCode">{{ study.StudyCode }}</span>
<span v-if="taskInfo && taskInfo.IsReadingTaskViewInOrder !== 0" class="study-code" :title="study.StudyCode">{{ study.StudyCode }}</span>
<span class="study-modality">{{ `${study.Modalities}(${study.SeriesCount})` }}</span>
<span class="patient-info" v-if="['PT、CT', 'CT、PT', 'PET-CT'].includes(study.Modalities)">
<el-popover placement="right-start" trigger="hover" popper-class="patient-info-popper">
@ -329,7 +332,13 @@ export default {
margin: 0;
text-align: center;
background-color: #4c4c4c;
height: 50px;
min-height: 50px;
height: auto;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: center;
word-break: break-word;
}
.dicom-desc {

View File

@ -7,8 +7,8 @@
<svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon"
@click.stop="viewCD(series.TaskInfo.VisitTaskId)" />
</div>
<h2 v-if="taskInfo.IsReadingShowSubjectInfo" class="subject-info">
{{ `${series.TaskInfo.SubjectCode} ${series.TaskInfo.TaskBlindName} ` }}
<h2 class="subject-info">
{{ taskInfo.IsReadingShowSubjectInfo ? series.TaskInfo.SubjectCode + ' ' + series.TaskInfo.TaskBlindName : series.TaskInfo.TaskBlindName }}
</h2>
<div>Series: #{{ series.SeriesNumber }}</div>
<div v-if="series.Stack">Image: #{{ `${series.SliceIndex + 1}/${series.Stack.length}` }}</div>

View File

@ -1,10 +1,12 @@
<template>
<div class="criterion-form-item">
<div v-if="!!question.GroupName && question.Type === 'group'"
<div
v-if="(!!question.GroupName && question.Type === 'group') && ((question.ShowQuestion === 1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion === 0)"
style="font-weight: bold;font-size: 16px;margin: 5px 0px;color:#fff;">
{{ question.GroupName }}
</div>
<div v-if="question.Type === 'table' || question.Type === 'basicTable'"
<div
v-if="(question.Type === 'table' || question.Type === 'basicTable') && ((question.ShowQuestion === 1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion === 0)"
style="font-weight: bold;font-size: 14px;margin: 5px 0px;">
<div style="display: flex;justify-content: space-between;align-items: center;color:#fff;margin: 10px 0 5px">
<span :title="question.Remark">{{ question.QuestionName }}</span>
@ -14,7 +16,8 @@
{{ $t('common:button:add') }}
</el-button>
</div>
<el-table :data="questionForm[question.Id]">
<el-table :data="questionForm[question.Id]"
v-if="(question.ShowQuestion === 1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion === 0">
<el-table-column :label="$t('CustomizeQuestionFormItem:label:OrderMark')" width="60px" show-overflow-tooltip>
<template slot-scope="scope">
{{ question.OrderMark }}{{ scope.$index + 1 }}

View File

@ -2,9 +2,16 @@
<div v-loading="loading" class="questionList-wrapper">
<div class="container">
<div class="basic-info">
<h3 v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo">
<span v-if="visitInfo.SubjectCode">{{ visitInfo.SubjectCode }} </span>
<span style="margin-left:5px;">{{ visitInfo.TaskBlindName }}</span>
<h3>
<span v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo && visitInfo.SubjectCode" style="margin-right:5px;">
{{ visitInfo.SubjectCode }}
</span>
<span>
<span v-if="taskInfo && !taskInfo.IsReadingShowSubjectInfo">
{{ $t('trials:reading:title:taskName') }}
</span>
{{ visitInfo.TaskBlindName }}
</span>
</h3>
<div v-if="readingTaskState < 2">
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')"

View File

@ -24,7 +24,7 @@
</el-select>
</el-form-item>
<!-- 受试者编号 -->
<el-form-item :label="$t('trials:medicalFeedback:table:subjectCode')">
<el-form-item v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0" :label="$t('trials:medicalFeedback:table:subjectCode')">
<el-input
v-model="searchData.SubjectCode"
style="width:130px;"
@ -32,7 +32,7 @@
/>
</el-form-item>
<!-- 盲态任务标识 -->
<!-- <el-form-item
<el-form-item
style="margin-bottom:10px"
:label="$t('trials:medicalFeedback:table:taskBlindName')"
>
@ -41,7 +41,7 @@
style="width:100px;"
clearable
/>
</el-form-item> -->
</el-form-item>
<!-- 任务类型 -->
<el-form-item
style="margin-bottom:10px"
@ -172,6 +172,7 @@
<!-- 受试者编号 -->
<el-table-column
v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0"
prop="SubjectCode"
min-width="100"
:label="$t('trials:medicalFeedback:table:subjectCode')"
@ -310,7 +311,6 @@
<el-table-column
:label="$t('common:action:action')"
min-width="100"
fixed="right"
>
<template slot-scope="scope">
<!-- 查看 -->
@ -409,12 +409,14 @@ export default {
chatForm: { visible: false, title: '' }, //
auditVisible: false,
trialCriterionList: [],
TrialReadingCriterionId: '0'
TrialReadingCriterionId: '0',
otherInfo: null
}
},
watch: {
TrialReadingCriterionId(v) {
if (v) {
this.searchData = searchDataDefault()
this.getList()
}
}
@ -437,6 +439,7 @@ export default {
getIRMedicalFeedbackList(this.searchData).then(res => {
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
this.otherInfo = res.OtherInfo
this.loading = false
}).catch(() => { this.loading = false })
},
@ -454,7 +457,11 @@ export default {
},
handleReply(row) {
this.currentRow = { ...row }
if (this.otherInfo && this.otherInfo.IsReadingTaskViewInOrder !== 0) {
this.chatForm.title = `${this.$t('trials:medicalFeedback:title:qaRecord')} (${row.SubjectCode} ${row.TaskBlindName})`
} else {
this.chatForm.title = `${this.$t('trials:medicalFeedback:title:qaRecord')} (${row.TaskBlindName})`
}
this.chatForm.visible = true
},
async nextTask(taskMedicalReviewId) {

View File

@ -13,9 +13,13 @@
</el-select>
</el-form-item>
<!-- 受试者编号 -->
<el-form-item :label="$t('trials:readTask:table:subjectCode')">
<el-form-item v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0" :label="$t('trials:readTask:table:subjectCode')">
<el-input v-model="searchData.SubjectCode" style="width:130px;" clearable />
</el-form-item>
<!-- 任务名称 -->
<el-form-item :label="$t('trials:readTask:table:blindName')">
<el-input v-model="searchData.TaskBlindName" style="width:130px;" clearable />
</el-form-item>
<!-- 任务状态 -->
<el-form-item style="margin-bottom:10px" :label="$t('trials:readTask:table:taskState')">
<el-select v-model="searchData.TaskState" clearable style="width:120px;">
@ -70,7 +74,7 @@
show-overflow-tooltip
/> -->
<!-- 受试者编号 -->
<el-table-column prop="SubjectCode" min-width="100" :label="$t('trials:readTask:table:subjectCode')"
<el-table-column v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0" prop="SubjectCode" min-width="100" :label="$t('trials:readTask:table:subjectCode')"
sortable="custom" show-overflow-tooltip />
<!-- 盲态任务标识 -->
<el-table-column prop="TaskBlindName" min-width="100" :label="$t('trials:readTask:table:blindName')"
@ -149,7 +153,7 @@
scope.row.ReReadingApplyState) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')" width="250" fixed="right">
<el-table-column :label="$t('common:action:action')" width="200" >
<template slot-scope="scope">
<!-- 查看 -->
<el-button circle :title="$t('trials:readTask:button:view')" icon="el-icon-view"
@ -177,7 +181,8 @@
custom-class="base-dialog-wrapper">
<el-form ref="reasonForm" :rules="rules" :model="ApplyforReasonForm" class="demo-ruleForm" size="small"
label-width="380px">
<p>{{ $t('trials:readTask:applyReread:title').replace('xxx', rowData.SubjectCode).replace('yyy', rowData.TaskBlindName) }}</p>
<p v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0">{{ $t('trials:readTask:applyReread:title').replace('xxx', rowData.SubjectCode).replace('yyy', rowData.TaskBlindName) }}</p>
<p v-else>{{ $t('trials:readTask:applyReread:title2').replace('yyy', rowData.TaskBlindName) }}</p>
<!-- 申请原因 -->
<el-divider content-position="left">{{ $t('trials:readTask:title:applyReason') }}</el-divider>
<!-- 申请原因 -->
@ -209,7 +214,7 @@
</el-form-item>
<!-- 是否复制阅片表单 -->
<el-form-item :label="$t('trials:readTask:title:IsCopyLesionAnswer')"
v-if="ApplyforReasonForm.IsCopyOrigenalForms && isTumor && rowData.ReadingCategory === 1" prop="IsCopyFollowForms" :rules="[
v-if="ApplyforReasonForm.IsCopyOrigenalForms && rowData.ReadingCategory === 1 && otherInfo.IsReadingTaskViewInOrder === 1" prop="IsCopyFollowForms" :rules="[
{ required: true, message: $t('common:ruleMessage:select') },
]">
<el-radio-group v-model="ApplyforReasonForm.IsCopyFollowForms">
@ -229,7 +234,7 @@
<el-table-column prop="TrialSiteCode" :label="$t('trials:readTask:table:siteCode')" min-width="100"
show-overflow-tooltip />
<!-- 受试者编号 -->
<el-table-column prop="SubjectCode" :label="$t('trials:readTask:table:subjectCode')" min-width="120"
<el-table-column v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0" prop="SubjectCode" :label="$t('trials:readTask:table:subjectCode')" min-width="120"
show-overflow-tooltip />
<!-- <el-table-column
prop="VisitTaskNum"
@ -331,6 +336,7 @@ import { openWindow } from "@/utils/splitScreen";
const searchDataDefault = () => {
return {
SubjectCode: '',
TaskBlindName: '',
SortField: '',
PageIndex: 1,
PageSize: 20,
@ -366,12 +372,14 @@ export default {
},
trialCriterionList: [],
TrialReadingCriterionId: '0',
openWindow: null
openWindow: null,
otherInfo: null
}
},
watch: {
TrialReadingCriterionId(v) {
if (v) {
this.searchData = searchDataDefault()
this.getList()
}
}
@ -413,6 +421,7 @@ export default {
getIRHaveReadTaskList(this.searchData).then(res => {
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
this.otherInfo = res.OtherInfo
this.loading = false
}).catch(() => { this.loading = false })
},
@ -482,7 +491,7 @@ export default {
if (!valid) return
this.loading = true
this.btnLoading = true
if (!this.ApplyforReasonForm.IsCopyOrigenalForms || !this.isTumor) {
if (!this.ApplyforReasonForm.IsCopyOrigenalForms) {
this.ApplyforReasonForm.IsCopyFollowForms = false
}
var params = {
@ -496,6 +505,7 @@ export default {
// IsCopyLesionAnswer: this.ApplyforReasonForm.IsCopyOrigenalForms,
RequestReReadingReason: this.ApplyforReasonForm.Type === 2 ? this.ApplyforReasonForm.RequestReReadingReason : this.$t('trials:readTask:option:errorRecords') // ''
}
console.log(params)
applyReReading(params).then(res => {
this.loading = false
this.btnLoading = false

View File

@ -78,7 +78,7 @@
{{ scope.row.SuggesteFinishedTime.split(':')[0] + ':00:00' }}
</template>
</el-table-column>
<el-table-column :label="$t('common:action:action')" width="250" fixed="right">
<el-table-column :label="$t('common:action:action')" width="250" >
<template slot-scope="scope">
<!-- 阅片 -->
<el-button :disabled="scope.row.ExistReadingApply" circle :title="scope.row.ExistReadingApply
@ -234,6 +234,7 @@ export default {
watch: {
TrialReadingCriterionId(v) {
if (v) {
this.searchData = searchDataDefault()
this.getList()
}
},

View File

@ -35,7 +35,7 @@
</el-select>
</el-form-item>
<!-- 受试者编号 -->
<el-form-item :label="$t('trials:rereadTask:table:subjectCode')">
<el-form-item v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0" :label="$t('trials:rereadTask:table:subjectCode')">
<el-input v-model="searchData.SubjectCode" style="width:100px;" />
</el-form-item>
<!-- <el-form-item style="margin-bottom:10px" label="访视/阅片期名称">
@ -45,14 +45,14 @@
clearable
/>
</el-form-item> -->
<!-- 任务编号 -->
<!-- <el-form-item :label="$t('trials:rereadTask:table:taskCode')">
<!-- 任务名称 -->
<el-form-item :label="$t('trials:rereadTask:table:taskBlindName')">
<el-input
v-model="searchData.TaskCode"
v-model="searchData.TaskBlindName"
style="width:130px;"
clearable
/>
</el-form-item> -->
</el-form-item>
<el-form-item :label="$t('trials:rereadTask:table:taskState')">
<el-select v-model="searchData.TaskState" clearable style="width:120px;">
<el-option v-for="i of $d.TaskState" :key="'TaskState' + i.label" :value="i.value" :label="i.label" />
@ -121,6 +121,7 @@
/>
<!-- 受试者编号 -->
<el-table-column
v-if="otherInfo && otherInfo.IsReadingTaskViewInOrder !== 0"
prop="OriginalReReadingTask.SubjectCode"
min-width="90"
:label="$t('trials:rereadTask:table:subjectCode')"
@ -303,6 +304,7 @@ const searchDataDefault = () => {
return {
IsUrgent: null,
SubjectCode: '',
TaskBlindName: '',
TaskCode: '',
PageIndex: 1,
PageSize: 20,
@ -330,12 +332,14 @@ export default {
},
ConfirmReReadingVisible: false,
trialCriterionList: [],
TrialReadingCriterionId: '0'
TrialReadingCriterionId: '0',
otherInfo: null
}
},
watch: {
TrialReadingCriterionId(v) {
if (v) {
this.searchData = searchDataDefault()
this.getList()
}
}
@ -373,6 +377,7 @@ export default {
getIRReReadingTaskList(this.searchData).then(res => {
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
this.otherInfo = res.OtherInfo
this.loading = false
}).catch(() => { this.loading = false })
},

View File

@ -192,8 +192,8 @@
<svg-icon style="cursor: pointer;" icon-class="documentation" class="svg-icon"
@click.stop="viewCD(v.taskInfo.VisitTaskId)" />
</div>
<h2 v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo && v.taskInfo" class="subject-info">
{{ `${taskInfo.SubjectCode} ${v.taskInfo.TaskBlindName} ` }}
<h2 class="subject-info">
{{ taskInfo && taskInfo.IsReadingShowSubjectInfo && v.taskInfo ? taskInfo.SubjectCode + ' ' + v.taskInfo.TaskBlindName : v.taskInfo.TaskBlindName }}
</h2>
<div v-if="v.currentFileName">{{ v.currentFileName }}</div>
</div>

View File

@ -171,6 +171,21 @@ export default {
document.addEventListener("click", this.foo);
},
methods: {
setDefaultRelatedStudyInfo(visitTaskInfo) {
if (!visitTaskInfo) return
const studyList = visitTaskInfo.StudyList || []
if (studyList.length === 0) return
const firstStudy = studyList[0]
const fileList = firstStudy.NoneDicomStudyFileList || []
if (fileList.length === 0) return
this.relatedStudyInfo = {
fileInfo: fileList[0],
visitTaskInfo,
fileList,
fileIndex: 0,
studyId: firstStudy.Id
}
},
handleReadingChart(row) {
let { e, data } = row
let obj = Object.assign({}, data)
@ -272,6 +287,9 @@ export default {
const idx = res.Result.findIndex(i => i.IsCurrentTask)
if (idx > -1) {
await this.setActiveTaskVisitId(res.Result[idx].VisitTaskId)
if (this.taskInfo.IsReadingTaskViewInOrder === 0) {
this.setDefaultRelatedStudyInfo(this.visitTaskList[idx])
}
this.$nextTick(() => {
this.$refs[res.Result[idx].VisitTaskId][0].setInitActiveFile()
})
@ -282,23 +300,15 @@ export default {
if (i > -1) {
await this.getReadingImageFile(res.Result[i].VisitTaskId, i)
await this.getAnnotations(res.Result[i].VisitTaskId, i)
const studyList = this.visitTaskList[i].StudyList
if (studyList.length > 0) {
const fileInfo = studyList[0].NoneDicomStudyFileList[0]
this.relatedStudyInfo = { fileInfo, visitTaskInfo: this.visitTaskList[i], fileList: studyList[0].NoneDicomStudyFileList, fileIndex: 0, studyId: studyList[0].Id }
this.setDefaultRelatedStudyInfo(this.visitTaskList[i])
if (!this.selectArr.includes(res.Result[i].VisitTaskId)) {
this.selectArr.push(res.Result[i].VisitTaskId)
}
}
}
}
if (this.taskInfo.IsReadingTaskViewInOrder === 2) {
//
const studyList = this.visitTaskList[idx].StudyList
if (studyList.length > 0) {
const fileInfo = studyList[0].NoneDicomStudyFileList[0]
this.relatedStudyInfo = { fileInfo, visitTaskInfo: this.visitTaskList[idx], fileList: studyList[0].NoneDicomStudyFileList, fileIndex: 0, studyId: studyList[0].Id }
}
this.setDefaultRelatedStudyInfo(this.visitTaskList[idx])
}
if (this.readingTaskState < 2) {
this.$refs[res.Result[idx].VisitTaskId][0].initCurrentMaredFiles()

View File

@ -4,7 +4,10 @@
<div v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo" :title="taskInfo.SubjectCode">
{{ taskInfo.SubjectCode }}
</div>
<div v-if="taskInfo && taskInfo.IsReadingShowSubjectInfo" :title="visitTaskInfo.TaskBlindName">
<div :title="visitTaskInfo.TaskBlindName">
<span v-if="taskInfo && !taskInfo.IsReadingShowSubjectInfo">
{{ $t('trials:reading:title:taskName') }}
</span>
{{ visitTaskInfo.TaskBlindName }}
</div>
</div>
@ -15,12 +18,13 @@
<div v-if="!study.IsCriticalSequence" class="dicom-desc">
<!-- <div v-if="taskInfo && taskInfo.IsShowStudyName">{{ study.StudyName }}</div> -->
<div style="text-overflow: ellipsis;overflow: hidden;">
<span :title="study.CodeView">{{ study.CodeView }}</span>
<span v-if="taskInfo && taskInfo.IsReadingTaskViewInOrder !== 0" :title="study.CodeView">{{
study.CodeView }}</span>
<span v-if="taskInfo && taskInfo.IsShowStudyName" :title="study.StudyName" style="margin-left: 5px;">{{
study.StudyName }}</span>
</div>
<div style="text-overflow: ellipsis;overflow: hidden;">
<span :title="study.BodyPart">{{ getBodyPart(study.BodyPart, study.BodyPartForEditOther) }}</span>
<span :title="study.DisplayBodyPart">{{ study.DisplayBodyPart }}</span>
<span style="margin-left: 5px;" :title="study.Modality">{{ study.Modality }}</span>
</div>
</div>
@ -91,21 +95,29 @@ export default {
},
async mounted() {
this.taskInfo = JSON.parse(localStorage.getItem('taskInfo'))
this.studyList = this.visitTaskInfo.StudyList
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
this.studyList = this.decorateStudyList(this.visitTaskInfo.StudyList || [])
if (this.studyList.length === 0) return
this.$nextTick(() => {
this.activeStudy(this.studyList[0].Id)
})
this.BodyPart.Bodypart = await this.$getBodyPart(this.$route.query.trialId)
},
watch: {
activeFileIndex() {
if (this.$refs[`noneDicomRef_${this.activeFileIndex}`]) {
this.scrollElementToTop(this.$refs[`noneDicomRef_${this.activeFileIndex}`][0], {
offset: 50
})
}
},
},
methods: {
decorateStudyList(studyList = []) {
return studyList.map(study => ({
...study,
DisplayBodyPart: this.getBodyPart(study.BodyPart, study.BodyPartForEditOther)
}))
},
scrollElementToTop(element, options = {}) {
const container = this.$refs['studyBox_ps']
if (!container || !element) return
@ -122,6 +134,7 @@ export default {
},
getBodyPart(bodyPart, other) {
if (!bodyPart && !other) return ''
if (!bodyPart) return other || ''
var separator = ','
if (bodyPart.indexOf('|') > -1) {
separator = '|'
@ -142,6 +155,9 @@ export default {
},
//
setInitActiveFile() {
if (this.studyList.length === 0) {
this.studyList = this.decorateStudyList(this.visitTaskInfo.StudyList || [])
}
if (this.studyList.length === 0) return
this.$nextTick(() => {
this.activeStudy(this.studyList[0].Id)
@ -172,8 +188,9 @@ export default {
this.activeFileIndex = fIndex
},
activeStudy(id) {
if (this.activeNames.indexOf(id) > -1) return
this.activeNames.push(id)
const studyId = `${id}`
if (this.activeNames.indexOf(studyId) > -1) return
this.activeNames.push(studyId)
},
handleChange(v) {
console.log(v)
@ -227,7 +244,13 @@ export default {
margin: 0;
text-align: center;
background-color: #4c4c4c;
height: 50px;
min-height: 50px;
height: auto;
flex-shrink: 0;
display: flex;
flex-direction: column;
justify-content: center;
word-break: break-word;
}
.dicom-desc {

View File

@ -222,6 +222,9 @@
form.IseCRFShowInDicomReading = false
} else {
form.ReadingTaskViewEnum = 2
form.IsReadingShowSubjectInfo = false
form.IsReadingShowPreviousResults = false
form.IseCRFShowInDicomReading = true
}
if (CriterionType !== 10 && (v === 0 || v === 2)) {
form.IsReadingPeriod = false
@ -279,7 +282,7 @@
" prop="IsReadingShowSubjectInfo">
<el-radio-group v-model="form.IsReadingShowSubjectInfo" :disabled="isConfirm ||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit']) ||
!!form.IsReadingTaskViewInOrder
form.IsReadingTaskViewInOrder >= 0
">
<el-radio v-for="item of $d.YesOrNo" :key="'IsReadingShowSubjectInfo' + item.value" :label="item.value">
{{ item.label }}
@ -293,7 +296,7 @@
" prop="IsReadingShowPreviousResults">
<el-radio-group v-model="form.IsReadingShowPreviousResults" :disabled="isConfirm ||
!hasPermi(['trials:trials-panel:setting:reading-unit:edit']) ||
!!form.IsReadingTaskViewInOrder
form.IsReadingTaskViewInOrder >= 0
" @change="
(v) => {
if (!v) {

View File

@ -13,10 +13,13 @@
</el-form-item>
</el-form>
<el-table :data="tableList" border style="width: 100%">
<el-table-column v-for="item in tableKey" :key="item.key" :prop="item.key" :label="item.title">
<el-table-column v-for="(item, index) in tableKey" :key="item.key" :prop="item.key" :label="item.title">
<template slot-scope="scope">
<span :class="{ IsHighlight: scope.row.IsHighlight.includes(item.key) }">{{ scope.row[item.key]
}}</span>
<el-button icon="el-icon-view" circle v-if="index > 0 && scope.row[item.key]" size="mini"
style="margin-left: 5px;" :title="$t('common:button:view')"
@click="lookReadingResults(scope.row.VisitTaskId[item.key])"></el-button>
</template>
</el-table-column>
</el-table>
@ -49,6 +52,7 @@ import {
} from '@/api/trials'
import * as echarts from 'echarts/core';
import { LineChart } from 'echarts/charts';
import { getToken } from '@/utils/auth'
import {
TitleComponent,
TooltipComponent,
@ -108,13 +112,33 @@ export default {
tableKey: [],
tableList: [],
R1ChartList: [],
R2ChartList: []
R2ChartList: [],
openWindow: null
}
},
mounted() {
this.getTrialCriterionList()
},
methods: {
//
lookReadingResults(id) {
if (this.openWindow) {
this.openWindow.close()
}
var token = getToken()
var path = null
let trialCriterion = this.trialCriterionList.find(item => item.TrialReadingCriterionId === this.TrialReadingCriterionId)
let trialId = this.$route.query.trialId
if (trialCriterion.ReadingTool === 0 || trialCriterion.ReadingTool === 2 || trialCriterion.ReadingTool === 3) {
path = `/readingDicoms?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.data.Code}&subjectId=${this.data.Id}&visitTaskId=${id}&isReadingTaskViewInOrder=${trialCriterion.IsReadingTaskViewInOrder}&criterionType=${trialCriterion.CriterionType}&readingTool=${trialCriterion.ReadingTool}&TokenKey=${token}`
} else {
path = `/noneDicomReading?TrialReadingCriterionId=${this.TrialReadingCriterionId}&trialId=${trialId}&subjectCode=${this.data.Code}&subjectId=${this.data.Id}&visitTaskId=${id}&isReadingTaskViewInOrder=${trialCriterion.IsReadingTaskViewInOrder}&criterionType=${trialCriterion.CriterionType}&readingTool=${trialCriterion.ReadingTool}&TokenKey=${token}`
}
// const routeData = this.$router.resolve({
// path: `/readingPage?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.Id}&TokenKey=${token}`
// })
this.openWindow = window.open(path, '_blank')
},
handleChange(v) {
this.getList()
},
@ -159,12 +183,14 @@ export default {
this.tableList = []
if (Evaluation[1] && Evaluation[1].length > 0) {
let obj = {
IsHighlight: []
IsHighlight: [],
VisitTaskId: {}
}
this.tableKey.forEach((item, index) => {
if (index === 0) {
obj[item.key] = 'R1'
} else {
obj.VisitTaskId[item.key] = Evaluation[1][index - 1].VisitTaskId
obj[item.key] = Evaluation[1][index - 1].DictionaryCode ? this.$fd(Evaluation[1][index - 1].DictionaryCode, parseFloat(Evaluation[1][index - 1].Value)) : Evaluation[1][index - 1].Value
if (Evaluation[1][index - 1].IsHighlight) {
obj.IsHighlight.push(item.key)
@ -176,13 +202,17 @@ export default {
}
if (Evaluation[2] && Evaluation[2].length > 0) {
let obj = {
IsHighlight: []
IsHighlight: [],
VisitTaskId: {}
}
this.tableKey.forEach((item, index) => {
obj[item.key] = index === 0 ? 'R2' : Evaluation[2][index - 1].DictionaryCode ? this.$fd(Evaluation[2][index - 1].DictionaryCode, parseFloat(Evaluation[2][index - 1].Value)) : Evaluation[2][index - 1].Value
if (index > 0 && Evaluation[2][index - 1].IsHighlight) {
obj.IsHighlight.push(item.key)
}
if (index > 0) {
obj.VisitTaskId[item.key] = Evaluation[2][index - 1].VisitTaskId
}
})
this.tableList.push(obj)
}
@ -331,7 +361,7 @@ export default {
}
.IsHighlight {
color: red;
color: #00f;
}
.chartBox {

View File

@ -9,10 +9,10 @@
</el-radio-group>
</el-form-item>
<!-- Out Visit Date -->
<el-form-item v-if="form.Status == 2" :label="$t('trials:subject:table:outVisitDate')" prop="VisitOverTime">
<!-- <el-form-item v-if="form.Status == 2" :label="$t('trials:subject:table:outVisitDate')" prop="VisitOverTime">
<el-date-picker v-model="form.VisitOverTime" type="date" :picker-options="pickerOption"
value-format="yyyy-MM-dd" format="yyyy-MM-dd" />
</el-form-item>
</el-form-item> -->
<!-- 末次访视 -->
<el-form-item v-if="form.Status === 2" :label="$t('trials:subject:table:finalSubjectVisit')"
prop="FinalSubjectVisitId">
@ -21,14 +21,43 @@
<el-option v-for="item in subjectVisitOptions" :key="item.Id" :label="item.VisitName" :value="item.Id" />
</el-select>
</el-form-item>
<!-- 访视中原因-->
<el-form-item
v-if="(form.Status < data.Status && form.Status === 1) || (form.BackReason)"
:label="$t('trials:subject:table:outVisitReason')"
prop="BackReason"
:rules="[
{ required: this.form.Status < this.data.Status, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500`, trigger: ['blur'] }
]"
>
<el-input v-model="form.BackReason" type="textarea" autosize />
</el-form-item>
<!-- 结束访视的原因 -->
<el-form-item v-if="form.Status === 2" :label="$t('trials:subject:table:outVisitReason')" prop="Reason">
<el-form-item
v-if="form.Status === 2"
:label="$t('trials:subject:table:outVisitReason')"
prop="Reason"
:rules="[
{ required: this.form.Status < this.data.Status, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500`, trigger: ['blur'] }
]"
>
<el-input v-model="form.Reason" type="textarea" autosize />
</el-form-item>
<!-- 访视中止的原因 -->
<el-form-item v-if="form.Status === 3" :label="$t('trials:subject:table:outVisitReason')" prop="SuspendReason">
<el-form-item
v-if="form.Status === 3"
:label="$t('trials:subject:table:outVisitReason')"
prop="SuspendReason"
:rules="[
{ required: this.form.Status < this.data.Status, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500`, trigger: ['blur'] }
]"
>
<el-input v-model="form.SuspendReason" type="textarea" autosize />
</el-form-item>
</div>
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
<el-form-item style="text-align:right;">
@ -61,16 +90,16 @@ export default {
Status: 1,
OutEnrollmentTime: '',
Reason: '',
VisitOverTime: '',
// VisitOverTime: '',
FinalSubjectVisitId: '',
SuspendReason: ''
SuspendReason: '',
BackReason: ''
},
rules: {
OutEnrollmentTime: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }],
FinalSubjectVisitId: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }],
Reason: [{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500` }],
SuspendReason: [{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500` }],
VisitOverTime: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }]
// SuspendReason: [{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500` }],
// VisitOverTime: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }]
},
pickerOption: {
disabledDate: time => {
@ -91,6 +120,8 @@ export default {
methods: {
handleChange() {
if (this.form.Status !== 3) this.form.SuspendReason = ''
if (this.form.Status !== 2) this.form.Reason = ''
if (this.form.Status !== 1) this.form.BackReason = ''
},
async initForm() {
this.loading = true
@ -116,7 +147,7 @@ export default {
this.form.TrialId = this.trialId
this.form.TrialSiteId = this.data.TrialSiteId
if (this.form.Status !== 2) {
this.form.VisitOverTime = ''
// this.form.VisitOverTime = ''
this.form.FinalSubjectVisitId = ''
}
updateSubjectStatus(this.form).then(res => {