中心调研表功能完善

uat_us
caiyiling 2024-07-05 14:59:05 +08:00
parent 9cb9478848
commit 29dfe79acd
11 changed files with 2002 additions and 234 deletions

View File

@ -10,7 +10,7 @@ import { OSSclient } from './utils/oss'
NProgress.configure({ showSpinner: false }) NProgress.configure({ showSpinner: false })
const whiteList = ['/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/researchDetail_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms'] const whiteList = ['/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
router.beforeEach(async(to, from, next) => { router.beforeEach(async(to, from, next) => {
NProgress.start() NProgress.start()
@ -56,9 +56,10 @@ router.beforeEach(async(to, from, next) => {
/* has no token*/ /* has no token*/
if (whiteList.indexOf(to.path) !== -1) { if (whiteList.indexOf(to.path) !== -1) {
if (to.path === '/researchLogin') { if (to.path === '/researchLogin') {
console.log(to)
const flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i) const flag = navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i)
if (flag) { if (flag) {
next(`/researchLogin_m`) next(`/researchLogin_m?trialId=${to.query.trialId}&lang=${to.query.lang}`)
} else { } else {
next() next()
} }

View File

@ -1,80 +1,271 @@
<template> <template>
<div class="research_bs_content"> <div class="research_bs_content">
<div class="title">中心调研表</div> <el-form ref="researchBSForm" label-position="left" :model="form" :rules="rules">
<el-form label-position="left" label-width="120px" :model="form"> <div class="basic_content form-label-width">
<div class="basic_content"> <el-form-item :label="$t('trials:researchForm:title:researchSurveyStatus')">
<el-form-item label="项目编号"> <el-tag>{{ $fd('ResearchRecord', state) }}</el-tag>
<span>{{ form.name1 }}</span>
</el-form-item> </el-form-item>
<el-form-item label="试验方案号"> <!-- 项目编号 -->
<span>{{ form.name2 }}</span> <el-form-item :label="$t('trials:researchForm:form:trialId')">
<span>{{ form.TrialCode }}</span>
</el-form-item> </el-form-item>
<el-form-item label="试验名称"> <!-- 试验方案号 -->
<span>{{ form.name3 }}</span> <el-form-item :label="$t('trials:researchForm:form:researchNo')">
<span>{{ form.ResearchProgramNo }}</span>
</el-form-item> </el-form-item>
<el-form-item label="适应症类型"> <!-- 试验名称 -->
<span>{{ form.name4 }}</span> <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')">
<span>{{ form.IndicationType }}</span>
</el-form-item> </el-form-item>
</div> </div>
<div class="login_content"> <div class="login_content">
<el-form-item label="中心名称" prop="region"> <div class="form-label-width">
<el-select v-model="form.name5" placeholder="请选择活动区域" style="width:100%"> <el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
<el-option label="区域一" value="shanghai" /> <el-select
<el-option label="区域二" value="beijing" /> v-model="form.TrialSiteId"
</el-select> 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>
<!-- 中心编号 -->
<el-form-item v-if="form.TrialSiteId" :label="$t('trials:researchForm:form:siteId')">
<el-input v-model="form.TrialSiteCode" disabled />
</el-form-item>
<!-- 联系人 -->
<el-form-item :label="$t('trials:researchForm:form:contactor')" prop="UserName">
<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-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item>
<!-- 联系邮箱 -->
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')">
<el-input v-model="form.Email" disabled />
</el-form-item>
<!-- 平均刻盘周期 -->
<el-form-item :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>
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质技师证对应设备的大型设备上岗证 -->
<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-radio-group>
</el-form-item> </el-form-item>
<el-form-item label="邮箱"> <!-- 原因 -->
<el-input v-model="form.name4" /> <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"
/>
</el-form-item> </el-form-item>
<el-form-item label="验证码"> <!-- 研究单位疗效评估人员类型 -->
<div class="code_content"> <el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')" :label="$t('trials:researchForm:form:staffType')">
<el-input v-model="form.VerificationCode" /> <el-radio-group v-model="form.EfficacyEvaluatorType" :disabled="!(state === 0 && userTypeEnumInt === 0)|| isHistory">
<el-button type="primary" @click="handleSendCode"></el-button> <el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`" :label="item.value">{{ item.label }}</el-radio>
</div> </el-radio-group>
</el-form-item>
<!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
<el-form-item v-if="!notShowFieldList.includes('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>
</el-form-item>
<!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
<el-form-item
v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
>
<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-form-item> </el-form-item>
<!-- <div class="submit_content">
<el-button type="primary" size="large" @click="onSubmit"></el-button>
</div> -->
</div> </div>
</el-form> </el-form>
</div> </div>
</template> </template>
<script> <script>
import { getTrialSiteSelect } from '@/api/trials'
import { addOrUpdateTrialSiteSurvey } from '@/api/research'
export default { export default {
name: 'ResearchBasicInfo', name: 'ResearchBasicInfo',
props: {
isHistory: {
type: Boolean,
default: false
}
},
data() { data() {
var checkPhone = (rule, value, callback) => {
const phoneReg = /^[0-9]+$/
if (!value) {
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
} else {
setTimeout(() => {
if (phoneReg.test(value)) {
callback()
} else {
callback(new Error(this.$t('trials:researchForm:formRule:phone')))
}
}, 100)
}
}
return { return {
form: { form: {
name1: 'ZY20240516', Id: '',
name2: 'TEST', Sponsor: '', //
name3: 'TEST20240613', ResearchProgramNo: '', //
name4: '肺癌', ExperimentName: '',
name5: '', TrialCode: '', //
VerificationCode: '' TrialSiteCode: '',
} TrialSiteAliasName: '',
IndicationType: '', //
TrialSiteId: '', //
UserName: '', //
Phone: '', //
Email: '', //
AverageEngravingCycle: '',
IsConfirmImagingTechnologist: '',
NotConfirmReson: '',
EfficacyEvaluatorType: '',
IsFollowStudyParameters: '',
NotFollowReson: ''
},
rules: {
TrialSiteId: [
{ 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'] }
],
Phone: [
{ required: true, validator: checkPhone, trigger: 'blur' }
]
},
siteOptions: [],
loading: false,
state: null,
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
isShow: false,
notShowFieldList: []
} }
}, },
methods: { methods: {
onSubmit() {}, //
handleSendCode() { handleSave(isAutoCommit) {
console.log(1) return new Promise(async(resolve) => {
try {
const valid = await this.$refs['researchBSForm'].validate()
if (valid) {
this.loading = 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,
isConfirmImagingTechnologist: this.form.IsConfirmImagingTechnologist,
notConfirmReson: this.form.NotConfirmReson,
efficacyEvaluatorType: this.form.EfficacyEvaluatorType,
isFollowStudyParameters: this.form.IsFollowStudyParameters,
notFollowReson: this.form.NotFollowReson
}
const res = await addOrUpdateTrialSiteSurvey(param)
this.loading = false
if (res.IsSuccess && !isAutoCommit) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
}
resolve(true)
} else {
if (isAutoCommit) {
this.$message.error(this.$t('trials:researchForm:button:msg1'))
}
resolve(false)
}
} catch (e) {
console.log(e)
resolve(false)
}
})
},
//
async initForm(trialInfo, trialSiteSurvey, notShowFieldList) {
// site
const { Result } = await getTrialSiteSelect(this.$route.query.trialId)
this.siteOptions = Result
this.form.Id = trialSiteSurvey.Id
this.form.Sponsor = trialInfo.Sponsor //
this.form.ResearchProgramNo = trialInfo.ResearchProgramNo //
this.form.ExperimentName = trialInfo.ExperimentName
this.form.TrialCode = trialInfo.TrialCode //
this.form.TrialSiteCode = trialSiteSurvey.TrialSiteCode
this.form.TrialSiteAliasName = trialSiteSurvey.TrialSiteAliasName //
this.form.IndicationType = trialInfo.IndicationType //
this.form.TrialSiteId = trialSiteSurvey.TrialSiteId
this.form.UserName = trialSiteSurvey.UserName //
this.form.Phone = trialSiteSurvey.Phone //
this.form.Email = trialSiteSurvey.Email //
this.form.AverageEngravingCycle = trialSiteSurvey.AverageEngravingCycle
this.form.IsConfirmImagingTechnologist = trialSiteSurvey.IsConfirmImagingTechnologist
this.form.NotConfirmReson = trialSiteSurvey.NotConfirmReson
this.form.EfficacyEvaluatorType = trialSiteSurvey.EfficacyEvaluatorType
this.form.IsFollowStudyParameters = trialSiteSurvey.IsFollowStudyParameters
this.form.NotFollowReson = trialSiteSurvey.NotFollowReson
this.state = trialSiteSurvey.State
this.isShow = true
if (!notShowFieldList) return
this.notShowFieldList = notShowFieldList
},
handleSiteChange(val) {
var selected = this.siteOptions.find(item => item.TrialSiteId === val)
if (selected) {
this.form.TrialSiteCode = selected.TrialSiteCode
}
} }
} }
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.research_bs_content{ .research_bs_content{
.title{
margin-bottom: 5px;
line-height: 80px;
font-size: 28px;
font-weight: bold;
text-align: center;
background: #fff;
}
.basic_content{ .basic_content{
padding: 0 20px; padding: 0 20px;
background: #fff; background: #fff;
} }
.login_content{ .login_content{
padding: 0 20px; padding: 0 20px;
@ -89,13 +280,21 @@ export default {
margin-right: 10px; margin-right: 10px;
} }
} }
.form-label-width{
/deep/.el-form-item__label{
width: 140px;
}
/deep/.el-form-item__content{
margin-left: 140px;
}
}
.submit_content{ .submit_content{
margin-top: 20px; margin-top: 20px;
text-align: center; text-align: center;
} }
/deep/.el-form-item { /deep/.el-form-item {
margin-bottom: 0px; margin-bottom: 10px;
padding: 5px 0px; padding: 5px 0px;
border-bottom: 1px solid #f5f7fa; border-bottom: 1px solid #f5f7fa;
.el-form-item__content{ .el-form-item__content{

View File

@ -0,0 +1,168 @@
<template>
<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-select>
</el-form-item>
<!-- 扫描参数 -->
<el-form-item v-if="isShowParameters" :label="$t('trials:equiptResearch:form:param')">
<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>
<!-- 扫描仪型号 -->
<el-form-item :label="$t('trials:equiptResearch:form:model')">
<el-input v-model="form.ScannerType" />
</el-form-item>
<!-- 备注 -->
<el-form-item :label="$t('trials:equiptResearch:form:remark')">
<el-input v-model="form.Note" />
</el-form-item>
<div style="text-align: center">
<!-- 取消 -->
<el-button
size="small"
type="primary"
@click="handleCancel"
>
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button
size="small"
type="primary"
@click="handleSave"
>
{{ $t("common:button:save") }}
</el-button>
</div>
</el-form>
</div>
</template>
<script>
import { addOrUpdateTrialSiteEquipmentSurvey } from '@/api/research'
import { getQueryString } from '@/utils/history.js'
export default {
name: 'EquipmentForm',
props: {
equipmentInfo: {
type: Object,
default() {
return {}
}
},
trialSiteSurveyEquipmentType: {
type: String,
default: ''
},
isShowParameters: {
type: Boolean,
default: false
}
},
data() {
return {
form: {
Id: '',
EquipmentTypeId: '',
Parameters: '',
ManufacturerName: '',
ScannerType: '',
Note: '',
TrialSiteSurveyId: ''
},
rules: {
EquipmentTypeId: [
{ required: true, message: this.$t('trials:researchForm:formRule:select'), trigger: ['blur', 'change'] }
]
},
loading: false,
dictionaryList: {}
}
},
mounted() {
this.initForm()
},
methods: {
async initForm() {
Object.keys(this.equipmentInfo).forEach(key => {
this.form[key] = this.equipmentInfo[key]
})
},
//
async handleSave() {
try {
const validate = await this.$refs.equipmentForm.validate()
if (!validate) return
this.loading = true
if (!this.form.TrialSiteSurveyId) {
this.form.TrialSiteSurveyId = getQueryString('trialSiteSurveyId')
}
const trialId = getQueryString('trialId')
const res = await addOrUpdateTrialSiteEquipmentSurvey(trialId, this.form)
this.loading = false
if (res.IsSuccess) {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.$emit('getList')
this.$emit('close')
}
} catch (e) {
this.loading = false
console.log(e)
}
},
handleTrialRoleChange(v) {
if (v === 1) {
// crc
this.form.IsGenerateAccount = true
this.form.UserTypeId = this.crcId
} else if (v === 2) {
// cra
this.form.IsGenerateAccount = true
this.form.UserTypeId = this.craId
} else {
this.form.IsGenerateAccount = false
this.form.UserTypeId = ''
}
},
//
handleCancel() {
this.$emit('close')
}
}
}
</script>
<style lang="scss" scoped>
.equipment_form_content{
padding: 0 10px;
/deep/.el-form-item {
margin-bottom: 10px;
padding: 5px 0px;
border-bottom: 1px solid #f5f7fa;
.el-form-item__content{
color: #82848a;
}
}
}
</style>

View File

@ -1,10 +1,14 @@
<template> <template>
<div class="equipments_content"> <div class="equipments_content">
<div class="title"> <div class="title">
<div>设备调研</div> <div>{{ $t('trials:equiptResearch:title:equiptResearch') }}</div>
<div><el-button type="primary" icon="el-icon-plus" size="mini" @click="drawer = true">添加</el-button></div> <div>
<el-button type="primary" icon="el-icon-plus" size="mini" @click="handleAdd">
{{ $t('common:button:add') }}
</el-button>
</div>
</div> </div>
<div v-for="item in list" :key="item.name" class="participant_info"> <div v-for="item in list" :key="item.name" class="equipment_info">
<div class="p_icon"> <div class="p_icon">
<i class="el-icon-receiving" /> <i class="el-icon-receiving" />
</div> </div>
@ -15,89 +19,140 @@
overflow: 'hidden', overflow: 'hidden',
'text-overflow': 'ellipsis'}" 'text-overflow': 'ellipsis'}"
> >
<div class="p_text">{{ item.name }}</div> <div class="p_text">{{ item.EquipmentType }}</div>
<div class="p_text" style="margin:0 10px">{{ item.role }}</div> <div v-if="isShowParameters" class="p_text" style="margin-left:10px">{{ item.Parameters }}</div>
<div class="p_text">{{ item.phone }}</div> <div class="p_text" style="margin-left:10px">{{ item.ManufacturerName }}</div>
</div> </div>
<div class="p_text">{{ item.email }}</div> <div class="p_text">{{ item.ScannerType }}</div>
<div class="p_text">{{ item.site }}</div> <div class="p_text">{{ item.Note }}</div>
</div> </div>
<div class="p_func"> <div v-if="state === 0 && userTypeEnumInt === 0 && !isHistory" class="p_func">
<el-button type="text"><i class="el-icon-edit-outline" style="font-size: 20px;" /></el-button> <el-button type="text" @click="handleEdit(item)">
<el-button type="text"><i class="el-icon-delete" style="font-size: 20px;" /></el-button> <i class="el-icon-edit-outline" style="font-size: 20px;" />
</el-button>
<el-button type="text" @click="handleDelete(item)">
<i class="el-icon-delete" style="font-size: 20px;" />
</el-button>
</div> </div>
</div> </div>
<!-- 添加/编辑设备信息 -->
<el-drawer <el-drawer
title="添加" :title="title"
:visible.sync="drawer" :visible.sync="formVisible"
direction="btt" direction="btt"
size="50%" size="50%"
> >
<div style="padding: 0 10px"> <EquipmentForm
<el-form :model="form" label-width="80px" label-position="left"> v-if="formVisible"
<el-form-item label="扫描设备"> :equipment-info="equipmentInfo"
<el-input v-model="form.name" /> :is-show-parameters="isShowParameters"
</el-form-item> @getList="getList"
<el-form-item label="扫描参数"> @close="close"
<el-input v-model="form.name" /> />
</el-form-item>
<el-form-item label="扫描仪器制造商名称">
<el-select v-model="form.region">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="扫描仪型号">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="注意事项">
<el-input v-model="form.name" />
</el-form-item>
</el-form>
</div>
</el-drawer> </el-drawer>
</div> </div>
</template> </template>
<script> <script>
import { getTrialSiteEquipmentSurveyList, deleteTrialSiteEquipmentSurvey } from '@/api/research'
import EquipmentForm from './EquipmentForm'
import { getQueryString } from '@/utils/history.js'
export default { export default {
name: 'EquipmentsResearch', name: 'EquipmentsResearch',
components: { EquipmentForm },
props: {
trialSiteSurveyEquipmentType: {
type: String,
default: ''
},
isHistory: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
list: [ list: [],
{ formVisible: false,
name: '扫描设备1', title: '',
role: '扫描参数', equipmentInfo: {},
phone: '扫描仪型号', w: 0,
email: '扫描仪器制造商名称', loading: false,
site: '注意事项' userTypeEnumInt: 0,
}, state: null,
{ trialSiteSurveyId: '',
name: '扫描设备2', trialId: '',
role: '扫描参数', isShowParameters: false
phone: '扫描仪型号',
email: '扫描仪器制造商名称',
site: '注意事项'
}
],
drawer: false,
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
w: 0
} }
}, },
mounted() { mounted() {
this.w = document.body.clientWidth - 200 this.w = document.body.clientWidth - 200
if (zzSessionStorage.getItem('userTypeEnumInt')) {
this.userTypeEnumInt = zzSessionStorage.getItem('userTypeEnumInt') * 1
}
this.trialSiteSurveyId = getQueryString('trialSiteSurveyId')
this.trialId = getQueryString('trialId')
}, },
methods: { methods: {
//
async getList() {
try {
this.loading = true
const res = await getTrialSiteEquipmentSurveyList(this.trialSiteSurveyId)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result
}
} catch (e) {
this.loading = false
console.log(e)
}
},
//
handleAdd() {
this.equipmentInfo = {}
this.title = this.$t('trials:equiptResearch:dialogTitle:add')
this.formVisible = true
},
//
handleEdit(obj) {
this.equipmentInfo = Object.assign({ ...obj })
this.title = this.$t('trials:equiptResearch:dialogTitle:edit')
this.formVisible = true
},
//
async handleDelete(obj) {
try {
const confirm = await this.$confirm(
this.$t('trials:staffResearch:message:confirmDel'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await deleteTrialSiteEquipmentSurvey(obj.Id, this.trialId)
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex((item) => item.Id === obj.Id), 1)
this.$message.success(this.$t('trials:equiptResearch:message:delSuccessfully'))
}
} catch (e) {
this.loading = false
console.log(e)
}
},
initList(TrialSiteEquipmentSurveyList, trialSiteSurvey, isShowParameters) {
this.isShowParameters = isShowParameters
this.list = TrialSiteEquipmentSurveyList
this.state = trialSiteSurvey.State
this.$forceUpdate()
console.log(this.list)
},
//
close() {
this.formVisible = false
}
} }
} }
</script> </script>
@ -112,7 +167,7 @@ export default {
align-items: center; align-items: center;
margin-bottom: 10px; margin-bottom: 10px;
} }
.participant_info{ .equipment_info{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: space-around; justify-content: space-around;

View File

@ -0,0 +1,304 @@
<template>
<div
v-loading="loading"
class="participants_form_content"
>
<el-form
ref="participantForm"
:model="form"
:rules="rules"
label-width="80px"
label-position="left"
>
<!-- -->
<el-form-item
:label="$t('trials:staffResearch:form:lastName')"
prop="LastName"
>
<span>{{ form.LastName }}</span>
</el-form-item>
<!-- -->
<el-form-item
:label="$t('trials:staffResearch:form:firstName')"
prop="FirstName"
>
<span>{{ form.FirstName }}</span>
</el-form-item>
<!-- 电话号码 -->
<el-form-item
:label="$t('trials:staffResearch:form:phone')"
prop="Phone"
>
<span>{{ form.Phone }}</span>
</el-form-item>
<!-- 邮箱 -->
<el-form-item
:label="$t('trials:staffResearch:form:email')"
prop="Email"
>
<span>{{ form.Email }}</span>
</el-form-item>
<!-- 单位 -->
<el-form-item
:label="$t('trials:staffResearch:form:organization')"
prop="OrganizationName"
>
<span>{{ form.Email }}</span>
</el-form-item>
<!-- 用户类型 -->
<el-form-item v-if="form.IsGenerateAccount" :label="$t('trials:staffResearch:form:userType')" prop="UserTypeId">
<el-select v-model="form.UserTypeId" style="width: 100%" disabled>
<el-option v-for="item of userTypeOptions" :key="item.Id" :label="item.UserTypeShortName" :value="item.Id">
<span>{{ item.UserType }}</span>
</el-option>
</el-select>
</el-form-item>
<!-- 更新状态 -->
<el-form-item :label="$t('trials:staffResearch:form:updateState')">
<el-radio-group v-model="form.IsHistoryUserDeleted" style="width: 100%">
<el-radio v-for="item of $d.IsUserExitTrial" :key="`IsHistoryUserDeleted${item.value}`" :label="item.value">{{
item.label }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item
v-if="errorMsg"
label=""
>
<span
v-if="errorMsg"
style="font-size: 12px; color: #f66"
>
{{ errorMsg }}
</span>
</el-form-item>
<div style="text-align: center">
<!-- 取消 -->
<el-button
size="small"
type="primary"
@click="handleCancel"
>
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button
size="small"
type="primary"
@click="handleSave"
>
{{ $t("common:button:save") }}
</el-button>
</div>
</el-form>
</div>
</template>
<script>
import { addOrUpdateTrialSiteUserSurvey } from '@/api/research'
import { getUserTypeList } from '@/api/research'
import { getQueryString } from '@/utils/history.js'
export default {
name: 'ParticipantForm',
props: {
participantInfo: {
type: Object,
default() {
return {}
}
},
state: {
type: Number,
required: true
}
},
data() {
var validateEmail = (rule, value, callback) => {
if (value === '') {
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
} else {
var reg =
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
if (this.form.Email && reg.test(this.form.Email)) {
this.sendDisabled = false
callback()
} else {
callback(new Error(this.$t('trials:researchForm:formRule:email')))
this.sendDisabled = true
}
}
}
return {
form: {
Id: '',
LastName: null,
FirstName: null,
TrialRoleCode: null,
UserTypeId: null,
Phone: null,
Email: null,
OrganizationName: '',
IsGenerateAccount: false,
IsHistoryUserDeleted: ''
},
rules: {
LastName: [
{
required: true,
message: this.$t('trials:researchForm:formRule:specify'),
trigger: 'blur'
},
{
min: 0,
max: 50,
message: this.$t('trials:researchForm:formRule:maxLength'),
trigger: 'blur'
}
],
FirstName: [
{
required: true,
message: this.$t('trials:researchForm:formRule:specify'),
trigger: 'blur'
},
{
min: 0,
max: 50,
message: this.$t('trials:researchForm:formRule:maxLength'),
trigger: 'blur'
}
],
TrialRoleCode: [
{
required: true,
message: this.$t('trials:researchForm:formRule:select'),
trigger: ['blur', 'change']
}
],
UserTypeId: [
{
required: true,
message: this.$t('trials:researchForm:formRule:select'),
trigger: ['blur']
}
],
Phone: [
{
max: 50,
message: this.$t('common:ruleMessage:maxLength') + ' 50',
trigger: 'blur'
}
],
Email: [
{ required: true, validator: validateEmail, trigger: ['blur'] }
],
IsHistoryUserDeleted: [
{
required: true,
message: this.$t('trials:researchForm:formRule:select'),
trigger: ['blur', 'change']
}
]
},
userRoles: [],
userTypeOptions: [],
userTypeEnumInt: 0,
errorMsg: '',
loading: false
}
},
mounted() {
this.initForm()
},
methods: {
async initForm() {
this.loading = true
const res = await getUserTypeList(3)
if (res.IsSuccess) {
this.userTypeOptions = res.Result
var crcObj = res.Result.find((i) => i.UserTypeEnum === 2)
this.crcId = crcObj ? crcObj.Id : ''
var craObj = res.Result.find((i) => i.UserTypeEnum === 9)
this.craId = craObj ? craObj.Id : ''
}
Object.keys(this.participantInfo).forEach((key) => {
this.form[key] = this.participantInfo[key]
})
if (zzSessionStorage.getItem('userTypeEnumInt')) {
this.userTypeEnumInt = zzSessionStorage.getItem('userTypeEnumInt') * 1
}
this.loading = false
},
//
async handleSave() {
try {
const validate = await this.$refs.participantForm.validate()
if (!validate) return
this.loading = true
if (!this.form.TrialSiteSurveyId) {
this.form.TrialSiteSurveyId = getQueryString('trialSiteSurveyId')
}
const trialId = getQueryString('trialId')
const res = await addOrUpdateTrialSiteUserSurvey(trialId, this.form)
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('common:message:savedSuccessfully')
)
this.$emit('close', { id: res.Result, errorMessage: '' })
}
} catch (e) {
if (e.Result && e.Result.Id && e.ErrorMessage) {
this.$emit('close', {
id: e.Result.Id,
errorMessage: e.ErrorMessage
})
} else {
console.log(e)
}
this.loading = false
}
},
handleTrialRoleChange(v) {
if (v === 1) {
// crc
this.form.IsGenerateAccount = true
this.form.UserTypeId = this.crcId
} else if (v === 2) {
// cra
this.form.IsGenerateAccount = true
this.form.UserTypeId = this.craId
} else {
this.form.IsGenerateAccount = false
this.form.UserTypeId = ''
}
},
//
handleCancel() {
this.$emit('close')
},
handleIsCorrectChange(val) {
if (!val) {
this.form.IsGenerateAccount = false
}
},
handleIsGenerateAccountChange(val) {
if (!val) {
this.form.UserTypeId = ''
}
}
}
}
</script>
<style lang="scss" scoped>
.participants_form_content{
padding: 0 10px;
/deep/.el-form-item {
margin-bottom: 10px;
padding: 5px 0px;
border-bottom: 1px solid #f5f7fa;
.el-form-item__content{
color: #82848a;
}
}
}
</style>

View File

@ -1,10 +1,198 @@
<template> <template>
<div> <div class="participants_content">
历史人员 <div class="title">
<div>{{ $t('trials:staffResearch:title:historicalStaff') }}</div>
</div>
<div v-for="item in list" :key="item.Id" class="participant_info">
<div class="p_icon">
<i class="el-icon-user" />
</div>
<div class="p_info">
<div
class="p_info_basic"
:style="{maxWidth:w+'px','white-space': 'nowrap',overflow: 'hidden','text-overflow': 'ellipsis'}"
>
<div class="p_text">{{ `${item.LastName} / ${item.FirstName}` }}</div>
<div class="p_text" style="margin:0 10px">{{ $fd('SiteSurvey_UserRoles',item.TrialRoleCode) }}</div>
<div class="p_text">{{ item.Phone }}</div>
</div>
<div class="p_text">{{ item.Email }}</div>
<div class="p_text">{{ item.OrganizationName }}</div>
</div>
<div v-if="state === 0 && (userTypeEnumInt===0 ) && !isHistory" class="p_func">
<!-- 编辑 -->
<el-button
v-if="userTypeEnumInt===0"
type="text"
@click="editParticipant(item)"
>
<i class="el-icon-edit-outline" style="font-size: 20px;" />
</el-button>
</div>
</div>
<!-- 编辑人员信息 -->
<el-drawer
:title="title"
:visible.sync="formVisible"
direction="btt"
size="50%"
>
<HistoricalParticipantForm
v-if="formVisible"
:state="state"
:participant-info="participantInfo"
@getList="getList"
@close="close"
/>
</el-drawer>
</div> </div>
</template> </template>
<script> <script>
import { getTrialSiteUserSurveyList } from '@/api/research'
import HistoricalParticipantForm from './HistoricalParticipantForm'
import { getQueryString } from '@/utils/history.js'
export default { export default {
name: 'HisParticipantsResearch' name: 'HisParticipantsResearch',
components: { HistoricalParticipantForm },
props: {
isHistory: {
type: Boolean,
default: false
}
},
data() {
return {
loading: false,
list: [],
formVisible: false,
title: '',
participantInfo: null,
w: 0,
state: null,
trialSiteSurveyId: '',
trialId: '',
userTypeEnumInt: 0,
warningList: []
}
},
mounted() {
this.w = document.body.clientWidth - 200
if (zzSessionStorage.getItem('userTypeEnumInt')) {
this.userTypeEnumInt = zzSessionStorage.getItem('userTypeEnumInt') * 1
}
this.trialSiteSurveyId = getQueryString('trialSiteSurveyId')
this.trialId = getQueryString('trialId')
},
methods: {
//
async getList() {
try {
this.loading = true
var params = {
trialSiteSurveyId: this.trialSiteSurveyId,
isHistoryUser: true
}
const res = await getTrialSiteUserSurveyList(params)
this.loading = false
if (res.IsSuccess) {
res.Result.map(item => {
var obj = this.warningList.find(i => i.id === item.Id)
if (obj) {
item.ErrorMessage = obj.errorMessage
}
})
this.list = res.Result
}
} catch (e) {
this.loading = false
console.log(e)
}
},
//
editParticipant(row) {
this.participantInfo = Object.assign({ ...row })
this.title = this.$t('trials:staffResearch:dialogTitle:edit')
this.formVisible = true
},
//
initList(trialSiteUserSurveyList, trialSiteSurvey) {
this.list = trialSiteUserSurveyList
this.state = trialSiteSurvey.State
this.$forceUpdate()
},
//
async close(obj) {
this.formVisible = false
var idx = this.warningList.findIndex(i => i.id === obj.id)
if (idx > -1) {
this.warningList[idx].errorMessage = obj.errorMessage
} else {
this.warningList.push({ id: obj.id, errorMessage: obj.errorMessage })
}
this.getList()
}
}
} }
</script> </script>
<style lang="scss" scoped>
.participants_content{
background: #fff;
padding: 10px;
.title{
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}
.participant_info{
display: flex;
flex-direction: row;
justify-content: space-around;
align-items: center;
border-top: 1px solid #f5f7fa;
.p_icon{
width: 70px;
font-size: 25px;
font-weight: bold;
text-align: center;
}
.p_info{
position: relative;
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;
top: 50%;
transform: translateY(-50%);
right: 0;
height: 50px;
width: 1px;
background-color: #f5f7fa;
}
.p_info_basic{
display: flex;
flex-direction: row;
align-items: center;
}
.p_text{
line-height: 25px;
color: #82848a;
}
.p_func{
width: 80px;
padding: 0 10px;
text-align: center;
}
}
}
</style>

View File

@ -1,9 +1,13 @@
<template> <template>
<div class="research_note"> <div class="research_note">
<div class="title"> <div class="title">
备注 {{ $t('trials:equiptResearch:form:precautions') }}
</div> </div>
<ol> <ol v-if="siteSurveyNoteInfo">
<div v-if="$i18n.locale === 'zh'" v-html="siteSurveyNoteInfo.ReplaceContentCN" />
<div v-else v-html="siteSurveyNoteInfo.ReplaceContent" />
</ol>
<ol v-else>
<!-- 只要有可能请确保受试者使用上述指定的扫描仪器采集影像 --> <!-- 只要有可能请确保受试者使用上述指定的扫描仪器采集影像 -->
<li>{{ $t('trials:equiptResearch:form:item1') }}</li> <li>{{ $t('trials:equiptResearch:form:item1') }}</li>
<!-- 请确保对每位受试者的扫描参数在整个研究过程中保持一致 --> <!-- 请确保对每位受试者的扫描参数在整个研究过程中保持一致 -->
@ -14,11 +18,20 @@
<li>{{ $t('trials:equiptResearch:form:item4') }}</li> <li>{{ $t('trials:equiptResearch:form:item4') }}</li>
</ol> </ol>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
name: 'ResearchNotes' name: 'ResearchNotes',
data() {
return {
siteSurveyNoteInfo: null
}
},
methods: {
initPage(siteSurveyNoteInfo) {
this.siteSurveyNoteInfo = siteSurveyNoteInfo
}
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -0,0 +1,318 @@
<template>
<div
v-loading="loading"
class="participants_form_content"
>
<el-form
ref="participantForm"
:model="form"
:rules="rules"
label-width="80px"
label-position="left"
>
<!-- -->
<el-form-item
:label="$t('trials:staffResearch:form:lastName')"
prop="LastName"
>
<el-input
v-model="form.LastName"
:disabled="!(state === 0 && userTypeEnumInt === 0)"
/>
</el-form-item>
<!-- -->
<el-form-item
:label="$t('trials:staffResearch:form:firstName')"
prop="FirstName"
>
<el-input
v-model="form.FirstName"
:disabled="!(state === 0 && userTypeEnumInt === 0)"
/>
</el-form-item>
<!-- 角色 -->
<el-form-item
:label="$t('trials:staffResearch:form:role')"
prop="TrialRoleCode"
>
<el-select
v-model="form.TrialRoleCode"
:disabled="!(state === 0 && userTypeEnumInt === 0)"
style="width:100%"
@change="handleTrialRoleChange"
>
<el-option
v-for="item of $d.SiteSurvey_UserRoles"
:key="item.id"
:label="item.label"
:value="parseInt(item.value)"
/>
</el-select>
</el-form-item>
<!-- 电话号码 -->
<el-form-item
:label="$t('trials:staffResearch:form:phone')"
prop="Phone"
>
<el-input
v-model="form.Phone"
:disabled="!(state === 0 && userTypeEnumInt === 0)"
/>
</el-form-item>
<!-- 邮箱 -->
<el-form-item
:label="$t('trials:staffResearch:form:email')"
prop="Email"
>
<el-input
v-model="form.Email"
:disabled="!(state === 0 && userTypeEnumInt === 0)"
/>
</el-form-item>
<!-- 单位 -->
<el-form-item
:label="$t('trials:staffResearch:form:organization')"
prop="OrganizationName"
>
<el-input
v-model="form.OrganizationName"
:disabled="!(state === 0 && userTypeEnumInt === 0)"
/>
</el-form-item>
<el-form-item
v-if="errorMsg"
label=""
>
<span
v-if="errorMsg"
style="font-size: 12px; color: #f66"
>
{{ errorMsg }}
</span>
</el-form-item>
<div style="text-align: center">
<!-- 取消 -->
<el-button
size="small"
type="primary"
@click="handleCancel"
>
{{ $t("common:button:cancel") }}
</el-button>
<!-- 保存 -->
<el-button
size="small"
type="primary"
@click="handleSave"
>
{{ $t("common:button:save") }}
</el-button>
</div>
</el-form>
</div>
</template>
<script>
import { addOrUpdateTrialSiteUserSurvey } from '@/api/research'
import { getUserTypeList } from '@/api/research'
import { getQueryString } from '@/utils/history.js'
export default {
name: 'ParticipantForm',
props: {
participantInfo: {
type: Object,
default() {
return {}
}
},
state: {
type: Number,
required: true
}
},
data() {
var validateEmail = (rule, value, callback) => {
if (value === '') {
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
} else {
var reg =
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
if (this.form.Email && reg.test(this.form.Email)) {
this.sendDisabled = false
callback()
} else {
callback(new Error(this.$t('trials:researchForm:formRule:email')))
this.sendDisabled = true
}
}
}
return {
form: {
Id: '',
LastName: null,
FirstName: null,
TrialRoleCode: null,
UserTypeId: null,
Phone: null,
Email: null,
OrganizationName: '',
IsGenerateAccount: false,
IsDisable: false
},
rules: {
LastName: [
{
required: true,
message: this.$t('trials:researchForm:formRule:specify'),
trigger: 'blur'
},
{
min: 0,
max: 50,
message: this.$t('trials:researchForm:formRule:maxLength'),
trigger: 'blur'
}
],
FirstName: [
{
required: true,
message: this.$t('trials:researchForm:formRule:specify'),
trigger: 'blur'
},
{
min: 0,
max: 50,
message: this.$t('trials:researchForm:formRule:maxLength'),
trigger: 'blur'
}
],
TrialRoleCode: [
{
required: true,
message: this.$t('trials:researchForm:formRule:select'),
trigger: ['blur', 'change']
}
],
UserTypeId: [
{
required: true,
message: this.$t('trials:researchForm:formRule:select'),
trigger: ['blur']
}
],
Phone: [
{
max: 50,
message: this.$t('common:ruleMessage:maxLength') + ' 50',
trigger: 'blur'
}
],
Email: [
{ required: true, validator: validateEmail, trigger: ['blur'] }
]
},
userRoles: [],
userTypeOptions: [],
userTypeEnumInt: 0,
errorMsg: '',
crcId: '',
craId: '',
loading: false
}
},
mounted() {
this.initForm()
},
methods: {
async initForm() {
this.loading = true
const res = await getUserTypeList(3)
if (res.IsSuccess) {
this.userTypeOptions = res.Result
var crcObj = res.Result.find((i) => i.UserTypeEnum === 2)
this.crcId = crcObj ? crcObj.Id : ''
var craObj = res.Result.find((i) => i.UserTypeEnum === 9)
this.craId = craObj ? craObj.Id : ''
}
Object.keys(this.participantInfo).forEach((key) => {
this.form[key] = this.participantInfo[key]
})
if (zzSessionStorage.getItem('userTypeEnumInt')) {
this.userTypeEnumInt = zzSessionStorage.getItem('userTypeEnumInt') * 1
}
this.loading = false
},
//
async handleSave() {
try {
const validate = await this.$refs.participantForm.validate()
if (!validate) return
this.loading = true
if (!this.form.TrialSiteSurveyId) {
this.form.TrialSiteSurveyId = getQueryString('trialSiteSurveyId')
}
const trialId = getQueryString('trialId')
const res = await addOrUpdateTrialSiteUserSurvey(trialId, this.form)
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t('common:message:savedSuccessfully')
)
this.$emit('close', { id: res.Result, errorMessage: '' })
}
} catch (e) {
if (e.Result && e.Result.Id && e.ErrorMessage) {
this.$emit('close', {
id: e.Result.Id,
errorMessage: e.ErrorMessage
})
} else {
console.log(e)
}
this.loading = false
}
},
handleTrialRoleChange(v) {
if (v === 1) {
// crc
this.form.IsGenerateAccount = true
this.form.UserTypeId = this.crcId
} else if (v === 2) {
// cra
this.form.IsGenerateAccount = true
this.form.UserTypeId = this.craId
} else {
this.form.IsGenerateAccount = false
this.form.UserTypeId = ''
}
},
//
handleCancel() {
this.$emit('close')
},
handleIsCorrectChange(val) {
if (!val) {
this.form.IsGenerateAccount = false
}
},
handleIsGenerateAccountChange(val) {
if (!val) {
this.form.UserTypeId = ''
}
}
}
}
</script>
<style lang="scss" scoped>
.participants_form_content{
padding: 0 10px;
/deep/.el-form-item {
margin-bottom: 10px;
padding: 5px 0px;
border-bottom: 1px solid #f5f7fa;
.el-form-item__content{
color: #82848a;
}
}
}
</style>

View File

@ -1,111 +1,188 @@
<template> <template>
<div class="participants_content"> <div class="participants_content">
<div class="title"> <div class="title">
<div>新增人员</div> <div>{{ $t('trials:staffResearch:title:newStaff') }}</div>
<div><el-button type="primary" icon="el-icon-plus" size="mini" @click="drawer = true">添加</el-button></div> <div>
<el-button
type="primary"
icon="el-icon-plus"
size="mini"
@click="addParticipant"
>
{{ $t('common:button:add') }}
</el-button>
</div>
</div> </div>
<div v-for="item in list" :key="item.name" class="participant_info"> <div v-for="item in list" :key="item.Id" class="participant_info">
<div class="p_icon"> <div class="p_icon">
<i class="el-icon-user" /> <i class="el-icon-user" />
</div> </div>
<div class="p_info"> <div class="p_info">
<div <div
class="p_info_basic" class="p_info_basic"
:style="{maxWidth:w+'px','white-space': 'nowrap', :style="{maxWidth:w+'px','white-space': 'nowrap',overflow: 'hidden','text-overflow': 'ellipsis'}"
overflow: 'hidden',
'text-overflow': 'ellipsis'}"
> >
<div class="p_text">{{ item.name }}</div> <div class="p_text">{{ `${item.LastName} / ${item.FirstName}` }}</div>
<div class="p_text" style="margin:0 10px">{{ item.role }}</div> <div class="p_text" style="margin:0 10px">{{ $fd('SiteSurvey_UserRoles',item.TrialRoleCode) }}</div>
<div class="p_text">{{ item.phone }}</div> <div class="p_text">{{ item.Phone }}</div>
</div> </div>
<div class="p_text">{{ item.email }}</div> <div class="p_text">{{ item.Email }}</div>
<div class="p_text">{{ item.site }}</div> <div class="p_text">{{ item.OrganizationName }}</div>
</div> </div>
<div class="p_func"> <div v-if="state === 0 && (userTypeEnumInt===0 ) && !isHistory" class="p_func">
<el-button type="text"><i class="el-icon-edit-outline" style="font-size: 20px;" /></el-button> <!-- 编辑 -->
<el-button type="text"><i class="el-icon-delete" style="font-size: 20px;" /></el-button> <el-button
type="text"
:disabled="state!==0 || item.IsGenerateSuccess"
@click="editParticipant(item)"
>
<i class="el-icon-edit-outline" style="font-size: 20px;" />
</el-button>
<!-- 移除 -->
<el-button
type="text"
:disabled="state!==0 || item.IsGenerateSuccess"
@click="removeParticipant(item)"
>
<i class="el-icon-delete" style="font-size: 20px;" />
</el-button>
</div> </div>
</div> </div>
<!-- 添加/编辑人员信息 -->
<el-drawer <el-drawer
title="添加" :title="title"
:visible.sync="drawer" :visible.sync="formVisible"
direction="btt" direction="btt"
size="50%" size="50%"
> >
<div style="padding: 0 10px"> <ParticipantForm
<el-form :model="form" label-width="80px" label-position="left"> v-if="formVisible"
<el-form-item label="性"> :state="state"
<el-input v-model="form.name" /> :participant-info="participantInfo"
</el-form-item> @getList="getList"
<el-form-item label="名"> @close="close"
<el-input v-model="form.name" /> />
</el-form-item>
<el-form-item label="角色">
<el-select v-model="form.region">
<el-option label="区域一" value="shanghai" />
<el-option label="区域二" value="beijing" />
</el-select>
</el-form-item>
<el-form-item label="电话号码">
<el-input v-model="form.name" />
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.name" />
</el-form-item>
</el-form>
</div>
</el-drawer> </el-drawer>
</div> </div>
</template> </template>
<script> <script>
import { getTrialSiteUserSurveyList, deleteTrialSiteUserSurvey } from '@/api/research'
import ParticipantForm from './ParticipantForm'
import { getQueryString } from '@/utils/history.js'
export default { export default {
name: 'ParticipantsResearch', name: 'ParticipantsResearch',
components: { ParticipantForm },
props: {
isHistory: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
list: [ loading: false,
{ list: [],
name: '张三', formVisible: false,
role: 'CRC', title: '',
phone: '13000009999', participantInfo: null,
email: 'zhangsan@zhizhun.com', w: 0,
site: '人民医院' state: null,
}, trialSiteSurveyId: '',
{ trialId: '',
name: '李四', userTypeEnumInt: 0,
role: 'CRA', warningList: []
phone: '14555509999',
email: 'lisi@zhizhun.com',
site: '同济医院'
},
{
name: '王五',
role: 'CRA',
phone: '18888809999',
email: 'wang@zhizhun.com',
site: '协和医院'
}
],
drawer: false,
form: {
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: ''
},
w: 0
} }
}, },
mounted() { mounted() {
this.w = document.body.clientWidth - 200 this.w = document.body.clientWidth - 200
console.log(document.body.clientWidth) if (zzSessionStorage.getItem('userTypeEnumInt')) {
this.userTypeEnumInt = zzSessionStorage.getItem('userTypeEnumInt') * 1
}
this.trialSiteSurveyId = getQueryString('trialSiteSurveyId')
this.trialId = getQueryString('trialId')
}, },
methods: { methods: {
//
async getList() {
try {
this.loading = true
var params = {
trialSiteSurveyId: this.trialSiteSurveyId,
isHistoryUser: false
}
const res = await getTrialSiteUserSurveyList(params)
this.loading = false
if (res.IsSuccess) {
res.Result.map(item => {
var obj = this.warningList.find(i => i.id === item.Id)
if (obj) {
item.ErrorMessage = obj.errorMessage
}
})
this.list = res.Result
}
} catch (e) {
this.loading = false
console.log(e)
}
},
//
addParticipant() {
this.participantInfo = {}
this.title = this.$t('trials:staffResearch:dialogTitle:add')
this.formVisible = true
},
//
editParticipant(obj) {
this.participantInfo = Object.assign({ ...obj })
this.title = this.$t('trials:staffResearch:dialogTitle:edit')
this.formVisible = true
},
//
async removeParticipant(obj) {
try {
const confirm = await this.$confirm(
this.$t('trials:staffResearch:message:confirmDel'),
{
type: 'warning',
distinguishCancelAndClose: true
}
)
if (confirm !== 'confirm') return
this.loading = true
const res = await deleteTrialSiteUserSurvey(obj.Id, this.trialId)
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex((item) => item.Id === obj.Id), 1)
this.$message.success(this.$t('trials:staffResearch:message:delSuccessfully'))
}
} catch (e) {
this.loading = false
console.log(e)
}
},
isExistIncorrect() {
return this.list.some(item => item.IsCorrect === false)
},
//
initList(trialSiteUserSurveyList, trialSiteSurvey) {
this.list = trialSiteUserSurveyList
this.state = trialSiteSurvey.State
this.$forceUpdate()
},
//
async close(obj) {
this.formVisible = false
var idx = this.warningList.findIndex(i => i.id === obj.id)
if (idx > -1) {
this.warningList[idx].errorMessage = obj.errorMessage
} else {
this.warningList.push({ id: obj.id, errorMessage: obj.errorMessage })
}
this.getList()
}
} }
} }
</script> </script>

View File

@ -1,22 +1,46 @@
<template> <template>
<div class="research_detal_wrapper"> <div v-loading="loading" class="research_detal_wrapper">
<div class="d_title">中心调研表</div>
<div class="d_content"> <div class="d_content">
<!-- 项目基本信息 --> <!-- 项目基本信息 -->
<BasicInfo /> <BasicInfo ref="basicInfo" />
<!-- 历史人员 --> <!-- 历史人员 -->
<!-- <HistoricalParticipants /> --> <HistoricalParticipants ref="historicalParticipant" class="mt5" />
<!-- 新增人员 --> <!-- 新增人员 -->
<Participants style="margin-top: 5px" /> <Participants ref="participants" class="mt5" />
<!-- 设备调研 --> <!-- 设备调研 -->
<Equipments style="margin-top: 5px" /> <Equipments ref="equipments" class="mt5" />
<!-- 备注 --> <!-- 备注 -->
<Notes style="margin-top: 5px" /> <Notes ref="notes" class="mt5" />
</div>
<div class="d_footer">
<!-- 保存 -->
<el-button
v-if="state === 0 && userTypeEnumInt === 0 "
type="primary"
size="small"
@click="handleSave"
>
{{ $t('common:button:save') }}
</el-button>
<!-- 提交 -->
<el-button
v-if="(state === 0 && userTypeEnumInt === 0)"
type="primary"
size="small"
@click="handleSubmit('submit')"
>
{{ $t('trials:researchForm:button:submit') }}
</el-button>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import { getSiteSurveyInfo, trialSurveySubmit } from '@/api/research'
import { getQueryString } from '@/utils/history.js'
import BasicInfo from './components/BasicInfo' import BasicInfo from './components/BasicInfo'
// import HistoricalParticipants from './components/HistoricalParticipants' import HistoricalParticipants from './components/HistoricalParticipants'
import Participants from './components/Participants' import Participants from './components/Participants'
import Equipments from './components/Equipments' import Equipments from './components/Equipments'
import Notes from './components/Notes' import Notes from './components/Notes'
@ -24,14 +48,145 @@ export default {
name: 'ResearchMobileDetail', name: 'ResearchMobileDetail',
components: { components: {
BasicInfo, BasicInfo,
// HistoricalParticipants, HistoricalParticipants,
Participants, Equipments, Notes } Participants, Equipments, Notes
},
data() {
return {
trialId: this.$route.query.trialId,
trialSiteSurveyId: '',
loading: false,
state: null,
userTypeEnumInt: 0,
rejectVisible: false,
rejectForm: { reason: '' },
siteSurveyNoteInfo: null
}
},
mounted() {
this.trialSiteSurveyId = getQueryString('trialSiteSurveyId')
this.initPage()
if (zzSessionStorage.getItem('userTypeEnumInt')) {
this.userTypeEnumInt = zzSessionStorage.getItem('userTypeEnumInt') * 1
}
},
methods: {
//
async initPage() {
try {
this.loading = true
const res = await getSiteSurveyInfo(this.trialId, this.trialSiteSurveyId)
if (res.Result) {
if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) {
this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote')
}
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 = []
var newArr = []
res.Result.TrialSiteUserSurveyList.map(i => {
if (i.IsHistoryUser) {
historicalArr.push(i)
} else {
newArr.push(i)
}
})
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['notes'].initPage(this.siteSurveyNoteInfo)
}
this.loading = false
} catch (e) {
this.loading = false
console.log(e)
}
},
//
handleSave() {
this.$refs['basicInfo'].handleSave(false)
},
//
async handleSubmit(type) {
if (this.userTypeEnumInt === 0) {
try {
this.loading = true
const res = await this.$refs['basicInfo'].handleSave(true)
this.loading = false
if (res) {
this.submit(type)
}
} catch (e) {
this.loading = false
console.log(e)
}
} else {
this.submit(type)
}
},
submit(type) {
//
this.$confirm(this.userTypeEnumInt === 0 ? this.$t('trials:researchForm:message:submitWarning') : this.$t('trials:researchForm:message:submitWarning2'), {
type: 'warning',
distinguishCancelAndClose: true
}).then(() => {
this.loading = true
var param = {
TrialId: this.trialId,
TrialSiteSurveyId: this.trialSiteSurveyId
}
trialSurveySubmit(param).then((res) => {
this.loading = false
if (res.IsSuccess) {
this.initPage()
if (this.userTypeEnumInt !== 0) {
this.$emit('refreshPage')
}
if (type === 'approve') {
this.$message.success(this.$t('common:message:approvedSuccessfully'))
} else {
this.$message.success(this.$t('trials:researchForm:message:savedSuccessfully'))
}
}
}).catch(() => { this.loading = false })
}).catch(() => {})
},
// 退
handleBack() {
this.$router.push({ path: `/researchLogin_m?trialId=${this.trialId}&lang=${this.$i18n.locale}` })
}
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.research_detal_wrapper{ .research_detal_wrapper{
background-color:#f5f7fa; background-color:#f5f7fa;
.d_title{
margin-bottom: 5px;
line-height: 80px;
font-size: 28px;
font-weight: bold;
text-align: center;
background: #fff;
position: sticky;
top: 0;
z-index: 10;
}
// .d_content{
// }
.d_footer{
position: sticky;
bottom: 0;
z-index: 10;
background-color: #f8f8f8;
line-height: 50px;
text-align: center;
}
.mt5{
margin-top: 5px
}
} }
</style> </style>

View File

@ -1,65 +1,355 @@
<template> <template>
<div class="research_login_m_content"> <div class="research_login_m_content">
<div class="title">中心调研表</div> <div class="title">中心调研表</div>
<el-form label-position="left" label-width="120px" :model="form"> <el-form
ref="loginForm"
v-loading="loading"
label-position="left"
label-width="120px"
:model="form"
>
<div class="basic_content"> <div class="basic_content">
<el-form-item label="项目编号"> <!-- 项目编号 -->
<span>{{ form.name1 }}</span> <el-form-item
:label="$t('trials:researchForm:form:trialId')"
>
<span>{{ form.TrialCode }}</span>
</el-form-item> </el-form-item>
<el-form-item label="试验方案号"> <!-- 试验方案号 -->
<span>{{ form.name2 }}</span> <el-form-item
:label="$t('trials:researchForm:form:researchNo')"
>
<span>{{ form.ResearchProgramNo }}</span>
</el-form-item> </el-form-item>
<el-form-item label="试验名称"> <!-- 试验名称 -->
<span>{{ form.name3 }}</span> <el-form-item
:label="$t('trials:researchForm:form:researchName')"
>
<span>{{ form.ExperimentName }}</span>
</el-form-item> </el-form-item>
<el-form-item label="适应症类型"> <!-- 适应症类型 -->
<span>{{ form.name4 }}</span> <el-form-item
:label="$t('trials:researchForm:form:decleareType')"
>
<span>{{ form.IndicationType }}</span>
</el-form-item> </el-form-item>
</div> </div>
<div class="login_content"> <div class="login_content">
<el-form-item label="中心名称" prop="region"> <el-form-item
<el-select v-model="form.name5" placeholder="请选择活动区域" style="width:100%"> :label="$t('trials:researchForm:form:siteName')"
<el-option label="区域一" value="shanghai" /> prop="SiteId"
<el-option label="区域二" value="beijing" /> >
<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-select>
</el-form-item> </el-form-item>
<el-form-item label="邮箱"> <el-form-item
<el-input v-model="form.name4" /> v-if="form.TrialSiteId && isHaveSiteSurveyRecord"
label=""
style="text-align:right;"
>
<!-- 更新调研表 -->
<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=''"
>
{{ $t('trials:researchForm:button:cancelUpdateQsForm') }}
</el-link>
</el-form-item> </el-form-item>
<el-form-item label="验证码">
<!-- 原调研表填写人邮箱 -->
<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>
<el-form-item
:label="$t('trials:researchForm:form:verifyCode')"
>
<div class="code_content"> <div class="code_content">
<el-input v-model="form.VerificationCode" /> <el-input
<el-button type="primary" @click="handleSendCode"></el-button> 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> </div>
</el-form-item> </el-form-item>
<div class="submit_content"> <div class="submit_content">
<el-button type="primary" size="large" @click="onSubmit"></el-button> <el-button
type="primary"
@click="onSubmit"
>
提交
</el-button>
</div> </div>
</div> </div>
</el-form> </el-form>
</div> </div>
</template> </template>
<script> <script>
import { sendVerifyCode, verifySendCode, getTrialSurveyInitInfo } from '@/api/research'
import { getUserMenuTree, getUserPermissions } from '@/api/user'
import store from '@/store'
import { mapGetters, mapMutations } from 'vuex'
export default { export default {
name: 'ResearchMobileLogin', name: 'ResearchMobileLogin',
data() { data() {
return { var checkPhone = (rule, value, callback) => {
form: { const phoneReg = /^1[3|4|5|7|8][0-9]{9}$/
name1: 'ZY20240516', if (!value) {
name2: 'TEST', return callback(new Error(this.$t('trials:researchForm:formRule:specify')))
name3: 'TEST20240613',
name4: '肺癌',
name5: '',
VerificationCode: ''
} }
setTimeout(() => {
if (!Number.isInteger(+value)) {
callback(new Error(this.$t('trials:researchForm:formRule:phone')))
} else {
if (phoneReg.test(value)) {
callback()
} else {
callback(new Error(this.$t('trials:researchForm:formRule:phone')))
}
}
}, 100)
}
var validateEmail = (rule, value, callback) => {
if (value === '') {
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
} else {
var reg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
callback()
} else {
callback(new Error(this.$t('trials:researchForm:formRule:email')))
}
}
}
var validateReplaceEmail = (rule, value, callback) => {
if (value === '') {
callback(new Error(this.$t('trials:researchForm:formRule:specify')))
} else {
var reg = /^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
if (this.form.ReplaceUserEmailOrPhone && reg.test(this.form.ReplaceUserEmailOrPhone)) {
callback()
} else {
callback(new Error(this.$t('trials:researchForm:formRule:email')))
}
}
}
return {
trialId: '',
form: {
Sponsor: null, //
ResearchProgramNo: null, //
TrialCode: null, //
IndicationType: null, //
ExperimentName: '',
TrialSiteId: null, //
UserName: null, //
Phone: '', //
EmailOrPhone: '',
TrialSiteCode: '',
IsUpdate: false,
ReplaceUserEmailOrPhone: '',
VerificationCode: ''
},
rules: {
TrialSiteId: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: ['blur'] }
],
UserName: [
{ required: true, message: this.$t('trials:researchForm:formRule:specify'), trigger: ['blur'] },
{ min: 0, max: 50, message: this.$t('trials:researchForm:formRule:maxLength'), trigger: 'blur' }
],
Phone: [
{ required: true, validator: checkPhone, trigger: ['blur'] }
],
EmailOrPhone: [
{ required: true, validator: validateEmail, trigger: ['blur', 'change'] }
],
ReplaceUserEmailOrPhone: [
{ required: true, validator: validateReplaceEmail, trigger: ['blur'] }
],
VerificationCode: [{ required: true, validator: (rule, value, callback) => { !value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback() }, trigger: ['blur'] }]
},
siteOptions: [],
loading: false,
sendDisabled: false,
btnLoading: false,
sendTitle: '',
count: '',
timer: null,
msg: '',
lang: 'zh',
isHaveSiteSurveyRecord: false
}
},
computed: {
...mapGetters([
'asyncRoutes',
'routes',
'language'
])
},
mounted() {
this.$i18n.locale = this.$route.query.lang
this.setLanguage(this.$route.query.lang)
this.$updateDictionary()
if (this.$route.query.trialId) {
this.trialId = this.$route.query.trialId
this.initPage()
} }
}, },
methods: { methods: {
onSubmit() { ...mapMutations({ setLanguage: 'lang/setLanguage' }),
this.$router.push({ path: `/researchDetail_m` }) //
async initPage() {
try {
this.loading = true
const res = await getTrialSurveyInitInfo(this.trialId)
this.loading = false
if (res.IsSuccess) {
this.siteOptions = res.Result.TrialSiteSelectList
}
Object.keys(this.form).forEach(key => {
if (res.Result.hasOwnProperty(key)) {
this.form[key] = res.Result[key]
}
})
} catch (e) {
this.loading = false
console.log(e)
}
}, },
handleSendCode() { //
console.log(1) async onSubmit() {
const validate = await this.$refs.loginForm.validate()
if (!validate) return
try {
this.loading = true
if (!this.form.IsUpdate) {
this.form.ReplaceUserEmailOrPhone = ''
}
const param = {
trialSiteId: this.form.TrialSiteId,
userName: this.form.UserName,
phone: this.form.Phone,
verificationType: 0,
emailOrPhone: this.form.EmailOrPhone,
verificationCode: this.form.VerificationCode,
isUpdate: this.form.IsUpdate,
replaceUserEmailOrPhone: this.form.ReplaceUserEmailOrPhone,
trialId: this.trialId
}
const res = await verifySendCode(param)
if (res.IsSuccess) {
zzSessionStorage.clear()
this.$i18n.locale = this.$route.query.lang
this.setLanguage(this.$route.query.lang)
store.dispatch('user/setToken', res.Result.Token)
zzSessionStorage.setItem('TokenKey', res.Result.Token)
var permissions = await getUserPermissions()
var menuTree = await getUserMenuTree()
store.dispatch('user/setTree', menuTree.Result)
store.dispatch('user/setPermissions', permissions.Result)
this.$router.push({ path: `/researchDetail_m?trialId=${this.trialId}&trialSiteSurveyId=${res.Result.TrialSiteSurveyId}` })
this.loading = false
}
} catch (e) {
this.loading = false
this.sendDisabled = false
}
},
handleSiteChange(val) {
this.isHaveSiteSurveyRecord = false
var selected = this.siteOptions.find(item => item.TrialSiteId === val)
if (selected) {
this.form.TrialSiteCode = selected.TrialSiteCode
this.isHaveSiteSurveyRecord = selected.IsHaveSiteSurveyRecord
}
},
//
async handleSendCode() {
try {
this.loading = true
const param = {
Email: this.form.EmailOrPhone,
TrialId: this.trialId
}
const res = await sendVerifyCode(param)
if (res.IsSuccess) {
this.getCode()
this.loading = false
const msg = this.$t('trials:researchForm:tip:sendCode').replace('xxx', this.form.EmailOrPhone)
this.$message.success(msg)
} else {
this.$alert(res.ErrorMessage)
}
} catch (e) {
this.loading = false
console.log(e)
}
},
getCode() {
const TIME_COUNT = 60
if (!this.timer) {
this.count = TIME_COUNT
this.sendDisabled = true
this.timer = setInterval(() => {
if (this.count > 0 && this.count <= TIME_COUNT) {
this.sendTitle = `(${this.count}s)`
this.count--
} else {
this.sendDisabled = false
this.sendTitle = ''
clearInterval(this.timer)
this.timer = null
}
}, 1000)
}
},
onCancel() {
this.$refs['loginForm'].resetFields()
} }
} }
} }
@ -98,7 +388,7 @@ export default {
} }
/deep/.el-form-item { /deep/.el-form-item {
margin-bottom: 0px; margin-bottom: 10px;
padding: 5px 0px; padding: 5px 0px;
border-bottom: 1px solid #f5f7fa; border-bottom: 1px solid #f5f7fa;
.el-form-item__content{ .el-form-item__content{