You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
500 lines
13 KiB
500 lines
13 KiB
<template>
|
|
<div class="problem-feedback-box" ref="containerRef">
|
|
<van-sticky class="problem-feedback-title" :container="containerRef">
|
|
<div class="problem-title">
|
|
<h2>问题反馈</h2>
|
|
<a class="close-popup" href="javascript:;" @click.stop="handleClose"></a>
|
|
</div>
|
|
</van-sticky>
|
|
<div class="problem-feedback-form">
|
|
<van-form @submit="submitForm" ref="feedbackformRef">
|
|
<div class="problem-feedback-item">
|
|
<h2 class="item-block-title">反馈信息录入</h2>
|
|
<van-field
|
|
readonly
|
|
clickable
|
|
is-link
|
|
:error="false"
|
|
name="picker"
|
|
:value="dataForm.feedbackSource"
|
|
label="移动端渠道"
|
|
placeholder="点击选择移动端渠道"
|
|
:rules="[{ required: true, message: '移动端渠道未选择,请选择后重新提交' }]"
|
|
@click="sourceShowPicker = true"
|
|
/>
|
|
<van-popup v-model:show="sourceShowPicker" position="bottom" round>
|
|
<van-picker
|
|
show-toolbar
|
|
title="移动端渠道"
|
|
:columns="sourceColumns"
|
|
@confirm="sourceOnConfirm"
|
|
:item-height="32"
|
|
:visible-item-count="5"
|
|
:loading="feedbackLoading"
|
|
@cancel="sourceShowPicker = false"
|
|
/>
|
|
</van-popup>
|
|
|
|
<van-field
|
|
readonly
|
|
clickable
|
|
is-link
|
|
name="picker"
|
|
:error="false"
|
|
:value="dataForm.businessType"
|
|
label="业务类型"
|
|
placeholder="点击选择业务类型"
|
|
:rules="[{ required: true, message: '业务类型未选择,请选择后重新提交' }]"
|
|
@click="typeShowPicker = true"
|
|
/>
|
|
<van-popup v-model:show="typeShowPicker" position="bottom" round>
|
|
<van-picker
|
|
show-toolbar
|
|
title="业务类型"
|
|
value-key="value"
|
|
:columns="typeColumns"
|
|
@confirm="typeOnConfirm"
|
|
:item-height="32"
|
|
:visible-item-count="5"
|
|
:loading="businessLoading"
|
|
@cancel="typeShowPicker = false"
|
|
/>
|
|
</van-popup>
|
|
|
|
<van-field
|
|
:error="false"
|
|
:rules="[{ required: true, message: '问题表述未填写,请填写后重新提交' }]"
|
|
v-model="dataForm.questionDesc"
|
|
rows="5"
|
|
clearable
|
|
label="问题描述"
|
|
maxlength="300"
|
|
type="textarea"
|
|
show-word-limit
|
|
:placeholder="feedbackPlaceholder"
|
|
/>
|
|
</div>
|
|
<div class="problem-feedback-item">
|
|
<h2 class="item-block-title">
|
|
上传图片<span class="title-tips">(上传对应问题的图像,最多上传5张)</span>
|
|
</h2>
|
|
<van-field
|
|
name="uploader"
|
|
:error="false"
|
|
:rules="[
|
|
{
|
|
required: true,
|
|
validator: validatorImgIds,
|
|
message: '图像未上传,请上传图像后重新提交',
|
|
},
|
|
]"
|
|
>
|
|
<template #input>
|
|
<van-uploader
|
|
v-model="dataForm.fileList"
|
|
:after-read="onAfterRead"
|
|
@oversize="onOversize"
|
|
:before-delete="deleteImage"
|
|
accept="image/*"
|
|
multiple
|
|
:max-count="5"
|
|
:max-size="5242880"
|
|
:preview-size="66"
|
|
upload-icon="plus"
|
|
/>
|
|
</template>
|
|
</van-field>
|
|
</div>
|
|
<div class="footer-btn">
|
|
<van-button type="primary" color="#5A9CFF" block round native-type="submitForm"
|
|
>确认提交</van-button
|
|
>
|
|
</div>
|
|
</van-form>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup>
|
|
import { ref, reactive, inject, onMounted } from 'vue'
|
|
import {
|
|
showToast,
|
|
showLoadingToast,
|
|
closeToast,
|
|
showDialog,
|
|
Field,
|
|
Sticky,
|
|
Button,
|
|
Form,
|
|
Popup,
|
|
Uploader,
|
|
Picker,
|
|
} from 'vant'
|
|
import { Post } from '@/utils/https'
|
|
import { compressImage } from '@/utils/CompressImage'
|
|
|
|
const emit = defineEmits(['handleClose'])
|
|
|
|
const store = inject('appStore', null)
|
|
const userId = inject('userId', ref(''))
|
|
const sessionId = inject('sessionId', ref(''))
|
|
const source = inject('source', ref(''))
|
|
const qaId = inject('qaId', ref(''))
|
|
const mescrollContent = inject('mescrollContent', ref(null))
|
|
|
|
const containerRef = ref(null)
|
|
const feedbackformRef = ref(null)
|
|
const hostname = window.location.protocol + '//' + window.location.host
|
|
|
|
const sourceColumns = ref([])
|
|
const typeColumns = ref([])
|
|
const feedbackCloseTip = ref('')
|
|
const sourceShowPicker = ref(false)
|
|
const typeShowPicker = ref(false)
|
|
const feedbackLoading = ref(false)
|
|
const businessLoading = ref(false)
|
|
const feedbackPlaceholder = ref(
|
|
'为更好定位并解决问题,问题表述中需包括但不限于问题发生的时间、具体功能模块及问题表现。如2020年8月25日12点30分操作身份认证时,其姓名处无法输入。'
|
|
)
|
|
|
|
const fileUpload = ref(new FormData())
|
|
|
|
const dataForm = reactive({
|
|
feedbackSource: '',
|
|
businessType: '',
|
|
businessType2: '',
|
|
questionDesc: '',
|
|
imgIds: [],
|
|
fileList: [],
|
|
})
|
|
|
|
onMounted(() => {
|
|
getData()
|
|
})
|
|
|
|
function getData() {
|
|
feedbackLoading.value = true
|
|
businessLoading.value = true
|
|
|
|
Post('config/feedbackConfig')
|
|
.then((res) => {
|
|
if (res.code && res.code != 0) {
|
|
showToast(res.msg)
|
|
return
|
|
}
|
|
|
|
if (res.data.feedbackBusinessType) {
|
|
typeColumns.value = JSON.parse(res.data.feedbackBusinessType)
|
|
feedbackLoading.value = false
|
|
}
|
|
if (res.data.feedbackSource) {
|
|
sourceColumns.value = JSON.parse(res.data.feedbackSource)
|
|
businessLoading.value = false
|
|
}
|
|
if (res.data.feedbackCloseTip) feedbackCloseTip.value = res.data.feedbackCloseTip
|
|
if (res.data.feedbackPlaceholder) feedbackPlaceholder.value = res.data.feedbackPlaceholder
|
|
})
|
|
.catch((error) => console.log(error))
|
|
}
|
|
|
|
function sourceOnConfirm(value) {
|
|
dataForm.feedbackSource = value
|
|
sourceShowPicker.value = false
|
|
}
|
|
|
|
function typeOnConfirm(value) {
|
|
dataForm.businessType = value.value
|
|
dataForm.businessType2 = value.label
|
|
typeShowPicker.value = false
|
|
}
|
|
|
|
function onOversize() {
|
|
showToast('文件大小不能超过5M')
|
|
}
|
|
|
|
function validatorImgIds() {
|
|
if (dataForm.imgIds.length > 0) return true
|
|
showToast('请等待图片上传完成,再提交')
|
|
return false
|
|
}
|
|
|
|
function asyncForEachFile(file) {
|
|
return new Promise((resolve) => {
|
|
getDataFiles(0, file.length)
|
|
function getDataFiles(i, len) {
|
|
file[i].status = 'uploading'
|
|
file[i].message = '上传中...'
|
|
|
|
compressAndUploadFile(file[i], (resultFile) => {
|
|
fileUpload.value.append('files', resultFile)
|
|
if (++i < len) {
|
|
getDataFiles(i, len)
|
|
} else {
|
|
resolve(fileUpload.value)
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
|
|
function onAfterRead(file) {
|
|
fileUpload.value = new FormData()
|
|
|
|
if (dataForm.fileList.length > 5) {
|
|
showToast('图片上传最多5张!')
|
|
dataForm.fileList.splice(5)
|
|
return
|
|
}
|
|
|
|
if (Array.isArray(file) && file.length) {
|
|
asyncForEachFile(file).then((result) => {
|
|
_uploadFile(
|
|
result,
|
|
(res) => {
|
|
if (res && res.length > 0) {
|
|
res.forEach((item, index) => {
|
|
file[index].status = 'success'
|
|
file[index].url = `${hostname}/liics_image${item.url}`
|
|
file[index].id = item.id
|
|
dataForm.imgIds.push(item.id)
|
|
})
|
|
}
|
|
},
|
|
() => {
|
|
file.forEach((item) => {
|
|
item.status = 'failed'
|
|
item.message = '上传失败...'
|
|
})
|
|
}
|
|
)
|
|
})
|
|
} else {
|
|
file.status = 'uploading'
|
|
file.message = '上传中...'
|
|
compressAndUploadFile(file, (resultFile) => {
|
|
fileUpload.value.append('files', resultFile)
|
|
_uploadFile(
|
|
fileUpload.value,
|
|
(res) => {
|
|
file.status = 'success'
|
|
file.url = `${hostname}/liics_image${res[0].url}`
|
|
file.id = res[0].id
|
|
dataForm.imgIds.push(res[0].id)
|
|
},
|
|
() => {
|
|
file.status = 'failed'
|
|
file.message = '上传失败...'
|
|
}
|
|
)
|
|
})
|
|
}
|
|
}
|
|
|
|
function deleteImage(file, name) {
|
|
const idx = name.index
|
|
if (!file.id) {
|
|
dataForm.fileList.splice(idx, 1)
|
|
return
|
|
}
|
|
|
|
const ids = [file.id]
|
|
showDialog({ title: '提示', message: `确定对[id=${ids.join(',')}]进行删除操作?` })
|
|
.then(() => {
|
|
const deleteToast = showLoadingToast({
|
|
message: '删除中...',
|
|
duration: 0,
|
|
loadingType: 'spinner',
|
|
forbidClick: true,
|
|
})
|
|
Post('upload/delete', ids)
|
|
.then((res) => {
|
|
closeToast()
|
|
if (res.code && res.code != 0) {
|
|
showToast(res.msg)
|
|
return
|
|
}
|
|
dataForm.fileList.splice(idx, 1)
|
|
dataForm.imgIds.splice(idx, 1)
|
|
})
|
|
.catch((error) => {
|
|
closeToast()
|
|
console.log(error)
|
|
})
|
|
})
|
|
.catch(() => console.log('取消删除'))
|
|
}
|
|
|
|
function compressAndUploadFile(file, callback) {
|
|
compressImage(file.content, { file, quality: 0.8 }).then((result) => {
|
|
const resultFile = result.blob.size > file.file.size ? file.file : result.blob
|
|
callback && callback(resultFile)
|
|
})
|
|
}
|
|
|
|
function _uploadFile(files, callback, errorCallback) {
|
|
upLoadImg('upload/images', files)
|
|
.then((res) => {
|
|
if (res.code && res.code != 0) {
|
|
showToast(res.msg)
|
|
return
|
|
}
|
|
callback && callback(res.data)
|
|
})
|
|
.catch((err) => errorCallback && errorCallback(err))
|
|
}
|
|
|
|
function upLoadImg(url, formData) {
|
|
return Post(url, formData, { headers: { 'Content-Type': 'multipart/form-data' } })
|
|
}
|
|
|
|
function handleClose() {
|
|
showDialog({
|
|
title: '关闭提示',
|
|
message: feedbackCloseTip.value,
|
|
cancelButtonText: '返回填写',
|
|
confirmButtonText: '坚持退出',
|
|
beforeClose: beforeClose,
|
|
}).catch((err) => console.log(err))
|
|
}
|
|
|
|
function beforeClose(action, done) {
|
|
if (action === 'confirm') {
|
|
closeDialog(
|
|
0,
|
|
() => {
|
|
done()
|
|
emit('handleClose', false)
|
|
},
|
|
() => done()
|
|
)
|
|
} else {
|
|
done()
|
|
}
|
|
}
|
|
|
|
function closeDialog(type, callback, errorBack) {
|
|
const params = {
|
|
userInfoId: userId.value,
|
|
sessionId: sessionId.value,
|
|
source: source.value,
|
|
qaId: qaId.value || '',
|
|
closeType: type || 0,
|
|
}
|
|
const closeToast = showLoadingToast({
|
|
message: '退出中...',
|
|
duration: 0,
|
|
loadingType: 'spinner',
|
|
forbidClick: true,
|
|
})
|
|
Post('question/feedbackClose', params)
|
|
.then((res) => {
|
|
closeToast()
|
|
callback && callback(res)
|
|
if (res.code && res.code != 0) {
|
|
showToast(res.msg)
|
|
return
|
|
}
|
|
setTimeout(() => {
|
|
store?.commit('set_chatList', res.data)
|
|
store?.commit('scrollBottom')
|
|
}, 200)
|
|
})
|
|
.catch((error) => {
|
|
closeToast()
|
|
errorBack && errorBack(error)
|
|
console.log(error)
|
|
})
|
|
}
|
|
|
|
function submitForm() {
|
|
const params = {
|
|
userInfoId: userId.value,
|
|
sessionId: sessionId.value,
|
|
source: source.value,
|
|
qaId: qaId.value || '',
|
|
feedbackSource: dataForm.feedbackSource,
|
|
businessType: dataForm.businessType2,
|
|
questionDesc: dataForm.questionDesc,
|
|
imgIds: dataForm.imgIds,
|
|
closeType: 0,
|
|
}
|
|
const submitToast = showLoadingToast({
|
|
message: '提交中...',
|
|
duration: 0,
|
|
loadingType: 'spinner',
|
|
forbidClick: true,
|
|
})
|
|
Post('question/feedbackSubmit', params)
|
|
.then((res) => {
|
|
closeToast()
|
|
if (res.code && res.code != 0) {
|
|
showToast(res.msg)
|
|
return
|
|
}
|
|
setTimeout(() => {
|
|
store?.commit('set_chatList', res.data)
|
|
store?.commit('scrollBottom')
|
|
}, 200)
|
|
emit('handleClose', false)
|
|
})
|
|
.catch((error) => {
|
|
closeToast()
|
|
console.log(error)
|
|
})
|
|
}
|
|
</script>
|
|
|
|
<style scoped>
|
|
.problem-feedback-box {
|
|
background: #f7f8fa;
|
|
min-height: 100vh;
|
|
}
|
|
|
|
.problem-feedback-title .problem-title {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 12px 16px;
|
|
background: #fff;
|
|
}
|
|
|
|
.problem-feedback-title h2 {
|
|
font-size: 18px;
|
|
font-weight: 600;
|
|
}
|
|
|
|
.close-popup {
|
|
width: 24px;
|
|
height: 24px;
|
|
background: url('data:image/svg+xml,...') no-repeat center;
|
|
background-size: contain;
|
|
}
|
|
|
|
.problem-feedback-form {
|
|
padding: 12px 16px;
|
|
}
|
|
|
|
.problem-feedback-item {
|
|
background: #fff;
|
|
border-radius: 8px;
|
|
padding: 16px;
|
|
margin-bottom: 12px;
|
|
}
|
|
|
|
.item-block-title {
|
|
font-size: 15px;
|
|
font-weight: 600;
|
|
margin-bottom: 8px;
|
|
}
|
|
|
|
.title-tips {
|
|
font-size: 12px;
|
|
color: #999;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.footer-btn {
|
|
margin-top: 24px;
|
|
padding-bottom: 24px;
|
|
}
|
|
</style>
|
|
|