irc_web/src/components/feedBack/index.vue

416 lines
12 KiB
Vue

<template>
<!--FEEDBACK-->
<div v-if="visible" @click.stop="() => false" class="feedBack-box">
<div class="feedBack-box-modal"></div>
<el-dialog
:visible.sync="visible"
v-dialogDrag
width="800px"
:close-on-click-modal="false"
@close="cancel"
:modal="false"
>
<div slot="title">
{{ title }}
</div>
<!-- 项目详情 -->
<div class="trialsBox" v-if="visitTaskId || SubjectVisitId">
<el-form
label-position="right"
:model="form"
:inline="true"
class="trialsForm"
v-if="type === 'detail'"
>
<el-form-item :label="$t('feedBack:trials:code')" style="width: 40%">
<span>{{ form.TrialCode }}</span>
</el-form-item>
<el-form-item :label="$t('feedBack:trials:name')" style="width: 40%">
<span>{{ form.ExperimentName }}</span>
</el-form-item>
<el-form-item
:label="$t('feedBack:trials:siteCode')"
style="width: 40%"
>
<span>{{ form.TrialSiteCode }}</span>
</el-form-item>
<el-form-item :label="$t('feedBack:trials:visit')" style="width: 40%">
<span>{{ form.SubjectCode }} - {{ form.SubjectVisitName }}</span>
</el-form-item>
</el-form>
</div>
<el-form
ref="feedBackForm"
label-position="right"
:model="form"
:rules="rules"
label-width="100px"
>
<!-- 影像异常tip -->
<p class="tip" v-if="type === 'imgfail'">
<i
class="el-icon-warning-outline"
style="color: #f56c6c; font-size: 24px"
></i>
<span>{{ $t('feedBack:imgfail:tip') }}</span>
</p>
<!-- 问题反馈 -->
<el-form-item
:label="$t('feedBack:form:feedBack')"
prop="QuestionType"
v-if="type === 'feedback' && trialId"
>
<el-select
v-model="form.QuestionType"
style="width: 100%"
popper-class="feedBack-select-box"
>
<el-option
v-for="item in QuestionTypeOptions"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<!-- 问题反馈 -->
<el-form-item
:label="$t('feedBack:form:feedBack')"
prop="QuestionType"
v-if="type === 'detail'"
>
<span>{{
QuestionTypeOptions.filter(
(item) => item.value === form.QuestionType
)[0].label
}}</span>
</el-form-item>
<!-- 问题描述 -->
<el-form-item
:label="$t('feedBack:form:description')"
prop="QuestionDescription"
>
<el-input
v-model="form.QuestionDescription"
type="textarea"
:rows="4"
:maxlength="500"
:disabled="type === 'detail'"
/>
</el-form-item>
<!-- 截图 -->
<el-form-item :label="$t('feedBack:form:screenshot')" prop="screenshot">
<uploadImage
:path.sync="form.ScreenshotList"
:isUpload.sync="loading"
:trialId="trialId"
:disabled="type === 'detail'"
ref="uploadImage"
/>
</el-form-item>
<!-- 反馈时间 -->
<el-form-item
:label="$t('feedBack:form:time')"
prop="screenshot"
v-if="type === 'detail'"
>
<span>{{ form.CreateTime }}</span>
</el-form-item>
<!-- 状态 -->
<el-form-item
:label="$t('feedBack:form:status')"
prop="screenshot"
v-if="type === 'detail' && level > 7"
>
<el-switch
v-model="form.State"
active-color="#13ce66"
inactive-color="#ff4949"
:active-value="1"
:inactive-value="0"
:active-text="$fd('FeedBackStatus', 1)"
:inactive-text="$fd('FeedBackStatus', 0)"
:disabled="level < 8 || !isStateChange"
@change="changeState"
>
</el-switch>
</el-form-item>
</el-form>
<div slot="footer" v-if="type !== 'detail' || isImgfail">
<!-- 取消 -->
<el-button size="small" @click.stop="cancel">
{{ $t('feedBack:button:cancel') }}
</el-button>
<!-- 保存 -->
<el-button
type="primary"
size="small"
@click.stop="save"
:loading="loading"
>
{{ $t('feedBack:button:save') }}
</el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import uploadImage from './uploadImage.vue'
import {
addOrUpdateUserFeedBack,
getUserFeedBackInfo,
batchUpdateFeedBackState,
} from '@/api/trials.js'
export default {
name: 'FB',
components: { uploadImage },
data() {
return {
title: null,
visible: false,
loading: false,
options: [],
type: null, // detail 表格详情 feedback 填写反馈 imgfail 影像异常
trialId: null, // 项目id
Id: null, // 反馈数据id
visitTaskId: null, // 任务id
isImgfail: false, // 是否是影像异常
isStateChange: true, // 是否可以切换状态
form: {
Id: null,
SubjectId: null,
SubjectVisitId: null,
QuestionType: 0,
QuestionDescription: null,
State: 0,
TrialSiteId: null,
TrialId: null,
VisitTaskId: null,
SubjectVisitId: null,
ScreenshotList: [],
ScreenshotListStr: null,
},
rules: {
QuestionType: [
{
required: true,
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
],
QuestionDescription: [
{
required: true,
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
{
validator: (rule, value, callback) => {
if (value.length < 5) {
callback(
new Error(this.$t('feedBack:ruleMessage:lengthLimitMin5'))
)
}
callback()
},
trigger: 'blur',
},
],
},
isUpload: false,
}
},
computed: {
level() {
if (this.hasPermi(['role:dev', 'role:admin'])) {
return 9
}
if (this.hasPermi(['role:pm', 'role:apm'])) {
return 8
}
if (this.hasPermi(['role:ir', 'role:crc'])) {
return 7
}
return 0
},
QuestionTypeOptions() {
if (this.level > 7) {
return [
...this.$d.FeedBackTypeToCRC.filter((item) => item.value > 0),
...this.$d.FeedBackTypeToIR,
]
}
if (this.hasPermi(['role:ir'])) {
return this.$d.FeedBackTypeToIR
}
if (this.hasPermi(['role:crc'])) {
return this.$d.FeedBackTypeToCRC
}
return []
},
},
methods: {
open(data) {
let { type, trialId, Id, visitTaskId, SubjectVisitId } = data
this.type = type
this.trialId = trialId
this.Id = Id
this.visitTaskId = visitTaskId
this.SubjectVisitId = SubjectVisitId
if (visitTaskId) {
this.isImgfail = true
}
this.setTypeOption()
if (!Id) {
this.title = this.setTitle()
}
if (Id || visitTaskId) {
this.getInfo(Id, visitTaskId)
}
this.visible = true
},
cancel() {
this.visible = false
this.$emit('closed')
},
async save() {
try {
let validate = await this.$refs.feedBackForm.validate()
if (!validate) return
if (this.trialId) {
this.form.TrialId = this.trialId
}
if (this.visitTaskId) {
this.form.VisitTaskId = this.visitTaskId
}
if (this.SubjectVisitId) {
this.form.SubjectVisitId = this.SubjectVisitId
}
if (this.Id) {
this.form.Id = this.Id
}
this.loading = true
let res = await addOrUpdateUserFeedBack(this.form)
this.loading = false
if (res.IsSuccess) {
this.$emit('success')
this.$message.success(this.$t('feedBack:save:success'))
this.cancel()
}
} catch (err) {
this.loading = false
console.log(err)
}
},
// 修改状态
async changeState() {
if (this.isImgfail) return
try {
let data = {
IdList: [this.Id],
State: this.form.State,
}
let res = await batchUpdateFeedBackState(data)
if (res.IsSuccess) {
this.$message.success(this.$t('feedBack:changeState:success'))
this.$emit('success')
// this.cancel();
this.getInfo(this.Id, this.visitTaskId)
}
} catch (err) {
console.log(err)
}
},
// 获取反馈详情
async getInfo(Id, visitTaskId) {
try {
let data = {
Id,
visitTaskId,
}
let res = await getUserFeedBackInfo(data)
if (res.IsSuccess && res.Result) {
this.form = res.Result
this.form.ScreenshotList = this.form.ScreenshotList || []
this.Id = res.Result.Id
if (res.Result.State > 0) {
this.isStateChange = false
}
if (res.Result.VisitTaskId) {
this.visitTaskId = res.Result.VisitTaskId
}
if (res.Result.SubjectVisitId) {
this.SubjectVisitId = res.Result.SubjectVisitId
}
let code = this.$fd('UserType', res.Result.UserTypeEnum)
this.title = this.setTitle(code, res.Result.FeedBackFullName)
if (visitTaskId) {
code = `${res.Result.SubjectCode}-${res.Result.SubjectVisitName}`
this.title = this.setTitle(code, res.Result.FeedBackFullName)
}
this.$refs.uploadImage.initFileList(res.Result.ScreenshotList)
}
} catch (err) {
console.log(err)
}
},
setTypeOption() {
if (!this.trialId) return (this.options = [])
if (this.hasPermi(['role:ir']))
return (this.option = this.$d.FeedBackTypeToIR)
if (this.hasPermi(['role:crc']))
return (this.option = this.$d.FeedBackTypeToCRC)
},
setTitle(code, name) {
if (this.hasPermi(['role:pm']) && this.visitTaskId) {
return `${this.$t('feedBack:form:title:pm2')}(${code}/${name})`
}
if (this.hasPermi(['role:pm', 'role:dev', 'role:admin'])) {
return `${this.$t('feedBack:form:title:pm')}(${code},${name})`
}
if (this.hasPermi(['role:ir', 'role:crc']) && this.type === 'detail') {
return `${this.$t('feedBack:form:detail:title')}`
}
if (this.hasPermi(['role:ir', 'role:crc'])) {
return `${this.$t('feedBack:form:title')}`
}
},
},
}
</script>
<style lang="scss" scoped>
.tip {
width: 86%;
margin: auto;
margin-bottom: 20px;
text-align: left;
padding: 0 10px;
display: flex;
align-items: center;
// border-radius: 5px;
// background-color: #eee;
i {
margin-right: 5px;
}
}
.trialsBox {
margin: auto;
margin-bottom: 20px;
text-align: left;
padding: 0 10px;
display: flex;
align-items: center;
border-radius: 5px;
background-color: #eee;
}
.trialsForm {
display: flex;
align-items: center;
justify-content: space-between;
flex-wrap: wrap;
.el-form-item {
margin-bottom: 10px;
}
}
</style>