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.
631 lines
17 KiB
631 lines
17 KiB
<script setup>
|
|
import { ref, computed, onMounted, watch, nextTick, onUnmounted } from "vue";
|
|
import { useDataStore } from '@/store/dataList.js'
|
|
import { addFeedbackAPI, getFeedbackAPI } from "../api/AIxiaocaishen"
|
|
import feedback from "../assets/img/Feedback/feedback.png";
|
|
import feedbackImg from "../assets/img/Feedback/feedbackImg.png";
|
|
import feedbackSuccess from "../assets/img/Feedback/feedbackSuccess.png";
|
|
import noFeedback from "../assets/img/Feedback/noFeedback.png";
|
|
import border from "../assets/img/Feedback/border.png";
|
|
import success from "../assets/img/Feedback/success.png";
|
|
import failure from "../assets/img/Feedback/failure.png";
|
|
import save from "../assets/img/Feedback/save.png";
|
|
import back from "../assets/img/Feedback/back.png";
|
|
import purpleDot from "../assets/img/Feedback/purpleDot.png";
|
|
import moment from 'moment';
|
|
|
|
const dataStore = useDataStore()
|
|
|
|
const feedbackContent = ref("");
|
|
const uploadUrl = import.meta.env.VITE_APP_IMG_API_BASE_URL;
|
|
const feedbackFileList = ref([]);
|
|
const isHistoryFeedback = ref(false);
|
|
|
|
const submitSuccessDialogVisible = ref(false)
|
|
const submitFailureDialogVisible = ref(false)
|
|
const submitFailureContent = ref('')
|
|
const feedbackSubmit = async () => {
|
|
console.log(feedbackContent.value)
|
|
console.log(feedbackFileList.value)
|
|
if (feedbackContent.value == '' && feedbackFileList.value.length == 0) {
|
|
submitFailureDialogVisible.value = true;
|
|
submitFailureContent.value = '请输入反馈内容或上传图片';
|
|
} else {
|
|
try {
|
|
let img1 = ''
|
|
let img2 = ''
|
|
let img3 = '';
|
|
if (feedbackFileList.value[0]) {
|
|
img1 = feedbackFileList.value[0].url;
|
|
}
|
|
if (feedbackFileList.value[1]) {
|
|
img2 = feedbackFileList.value[1].url;
|
|
}
|
|
if (feedbackFileList.value[2]) {
|
|
img3 = feedbackFileList.value[2].url;
|
|
}
|
|
console.log(img1, img2, img3);
|
|
const result = await addFeedbackAPI({
|
|
token: localStorage.getItem('localToken'),
|
|
content: feedbackContent.value,
|
|
image1: img1,
|
|
image2: img2,
|
|
image3: img3,
|
|
|
|
})
|
|
|
|
console.log(result)
|
|
|
|
feedbackHistory();
|
|
|
|
submitSuccessDialogVisible.value = true;
|
|
} catch (error) {
|
|
submitFailureDialogVisible.value = true;
|
|
submitFailureContent.value = '反馈提交异常(错误代码:' + error.response.status + '),建议尝试更换网络环境后重新提交。';
|
|
}
|
|
}
|
|
}
|
|
|
|
const feedbackHistoryList = ref([])
|
|
|
|
const feedbackHistory = async () => {
|
|
try {
|
|
const result = await getFeedbackAPI({
|
|
token: localStorage.getItem('localToken'),
|
|
})
|
|
console.log(result)
|
|
|
|
if (result.data.length > 0) {
|
|
isHistoryFeedback.value = true;
|
|
|
|
feedbackHistoryList.value = result.data;
|
|
|
|
} else {
|
|
isHistoryFeedback.value = false;
|
|
}
|
|
|
|
} catch (error) {
|
|
console.log(error)
|
|
}
|
|
}
|
|
|
|
const submitSuccessConfirm = () => {
|
|
feedbackContent.value = '';
|
|
feedbackFileList.value = [];
|
|
if (localStorage.getItem('feedbackContent')) {
|
|
localStorage.removeItem('feedbackContent');
|
|
}
|
|
if (localStorage.getItem('feedbackFileList')) {
|
|
localStorage.removeItem('feedbackFileList');
|
|
}
|
|
submitSuccessDialogVisible.value = false;
|
|
}
|
|
const submitFailureConfirm = () => {
|
|
submitFailureDialogVisible.value = false;
|
|
}
|
|
// 字数限制提示弹窗
|
|
const feedbackContentOverLengthDialogVisible = ref(false)
|
|
|
|
const feedbackContentLengthJudge = () => {
|
|
console.log('字数判断');
|
|
console.log(feedbackContent.value.length)
|
|
if (feedbackContent.value.length >= 2000) {
|
|
feedbackContentOverLengthDialogVisible.value = true;
|
|
}
|
|
}
|
|
|
|
const feedbackContentOverLengthConfirm = () => {
|
|
feedbackContentOverLengthDialogVisible.value = false;
|
|
}
|
|
|
|
const feedbackContentChange = () => {
|
|
console.log('内容改变');
|
|
console.log(feedbackContent.value)
|
|
|
|
localStorage.setItem('feedbackContent', feedbackContent.value);
|
|
}
|
|
|
|
const check = function (file, fileList) {
|
|
console.log('调用check方法');
|
|
console.log(fileList);
|
|
console.log(fileList.length);
|
|
}
|
|
|
|
const successChange = function (file, fileList) {
|
|
console.log('调用successChange方法');
|
|
console.log(fileList);
|
|
console.log(fileList.response);
|
|
if (fileList.response.code == 200) {
|
|
feedbackFileList.value.push(fileList.response.data)
|
|
}
|
|
console.log(feedbackFileList.value);
|
|
localStorage.setItem('feedbackFileList', JSON.stringify(feedbackFileList.value));
|
|
}
|
|
|
|
const dialogImageUrl = ref('')
|
|
const dialogVisible = ref(false)
|
|
|
|
const handleRemove = (uploadFile, uploadFiles) => {
|
|
console.log(uploadFile, uploadFiles)
|
|
feedbackFileList.value = uploadFiles;
|
|
console.log('调用handleRemove方法');
|
|
console.log(feedbackFileList.value);
|
|
console.log(feedbackFileList.value.length);
|
|
localStorage.setItem('feedbackFileList', JSON.stringify(feedbackFileList.value));
|
|
}
|
|
|
|
const handlePictureCardPreview = (uploadFile) => {
|
|
dialogImageUrl.value = uploadFile.url
|
|
dialogVisible.value = true
|
|
}
|
|
|
|
// 返回弹窗
|
|
const feedbackBackDialogVisible = ref(false)
|
|
|
|
const feedbackBack = () => {
|
|
if(feedbackContent.value == '' && feedbackFileList.value.length == 0) {
|
|
dataStore.isFeedback = false;
|
|
return;
|
|
}
|
|
feedbackBackDialogVisible.value = true;
|
|
}
|
|
// 确人保存
|
|
const feedbackBackConfirm = () => {
|
|
feedbackBackDialogVisible.value = false;
|
|
dataStore.isFeedback = false;
|
|
}
|
|
// 取消保存
|
|
const feedbackBackCancel = () => {
|
|
if (localStorage.getItem('feedbackContent')) {
|
|
localStorage.removeItem('feedbackContent');
|
|
}
|
|
if (localStorage.getItem('feedbackFileList')) {
|
|
localStorage.removeItem('feedbackFileList');
|
|
}
|
|
feedbackBackDialogVisible.value = false;
|
|
dataStore.isFeedback = false;
|
|
}
|
|
|
|
|
|
onMounted(() => {
|
|
feedbackHistory()
|
|
|
|
if (localStorage.getItem('feedbackContent')) {
|
|
feedbackContent.value = localStorage.getItem('feedbackContent')
|
|
} else {
|
|
feedbackContent.value = '';
|
|
}
|
|
if (localStorage.getItem('feedbackFileList')) {
|
|
feedbackFileList.value = JSON.parse(localStorage.getItem('feedbackFileList'));
|
|
} else {
|
|
feedbackFileList.value = [];
|
|
}
|
|
console.log(uploadUrl)
|
|
})
|
|
|
|
</script>
|
|
|
|
<template>
|
|
<el-container>
|
|
<div>
|
|
<div @click="feedbackBack">
|
|
<img :src="back" alt="返回按钮" class="backImg">
|
|
</div>
|
|
</div>
|
|
<el-scrollbar>
|
|
<el-header>
|
|
<div class="feedbackImgClass">
|
|
<img :src="feedback" alt="用户反馈" class="img">
|
|
<img :src="feedbackImg" alt="用户反馈" class="img">
|
|
</div>
|
|
</el-header>
|
|
<el-main>
|
|
<div class="card">
|
|
<div class="feedbackTitle header-item">
|
|
填写反馈内容
|
|
</div>
|
|
<div class="header-item">
|
|
<el-input class="feedbackContent" v-model="feedbackContent" :rows="5" type="textarea"
|
|
maxlength="2000" show-word-limit placeholder="请描写您想反馈的内容..." @change="feedbackContentChange"
|
|
@input="feedbackContentLengthJudge" />
|
|
</div>
|
|
<div class="feedbackTitle header-item">
|
|
照片上传
|
|
</div>
|
|
<div class="header-item">
|
|
<el-upload class="uploadImg" :action="uploadUrl" list-type="picture-card" :auto-upload="true"
|
|
:on-success="successChange" accept=".png, .jpg, .jpeg, .ico," :on-change="check"
|
|
:file-list="feedbackFileList" :on-preview="handlePictureCardPreview"
|
|
:on-remove="handleRemove" :limit="3">
|
|
<el-icon>
|
|
<Plus />
|
|
</el-icon>
|
|
<template #tip>
|
|
<div class="el-upload__tip">
|
|
最多上传三张
|
|
</div>
|
|
</template>
|
|
</el-upload>
|
|
</div>
|
|
<div>
|
|
<div class="feedbackSubmitBtn" @click="feedbackSubmit">提 交</div>
|
|
</div>
|
|
</div>
|
|
<div class="card">
|
|
<div class="feedbackTitle">
|
|
历史反馈内容
|
|
</div>
|
|
<div v-if="isHistoryFeedback">
|
|
|
|
<div v-for="(item, index) in feedbackHistoryList" :key="index" class="feedbackHistory">
|
|
<div class="feedbackHistoryItem">
|
|
<div class="feedbackHistoryTitle">
|
|
<img :src="purpleDot" alt="紫点" class="purpleDot">
|
|
{{ moment(item.created_at).format('YYYY-MM-DD HH:mm') }}
|
|
<div class="feedbackSuccess">
|
|
<div class="feedbackSuccessWord">
|
|
反馈成功
|
|
</div>
|
|
<img class="feedbackSuccessImg" :src="feedbackSuccess" alt="成功">
|
|
</div>
|
|
</div>
|
|
<div class="feedbackHistoryContent">
|
|
{{ item.content }}
|
|
</div>
|
|
<div class="feedbackHistoryImg">
|
|
<el-image v-if="item.image1" :src="item.image1" alt="图片错误"
|
|
class="feedbackHistoryImgItem" :preview-src-list="[item.image1]" />
|
|
<el-image v-if="item.image2" :src="item.image2" alt="图片错误"
|
|
class="feedbackHistoryImgItem" :preview-src-list="[item.image2]" />
|
|
<el-image v-if="item.image3" :src="item.image3" alt="图片错误"
|
|
class="feedbackHistoryImgItem" :preview-src-list="[item.image3]" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div v-else>
|
|
<div class="noFeedback">
|
|
<img class="noFeedbackImg" :src="noFeedback" alt="暂无历史提交">
|
|
暂无记录
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</el-main>
|
|
</el-scrollbar>
|
|
</el-container>
|
|
|
|
<el-dialog v-model="dialogVisible">
|
|
<img w-full :src="dialogImageUrl" alt="Preview Image" />
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="feedbackBackDialogVisible" class="save-dialog">
|
|
<div class="imgLine">
|
|
<img class="dialogImg" :src="save" alt="保存">
|
|
</div>
|
|
<div class="feedbackBackTitle">
|
|
系统提示
|
|
</div>
|
|
<div class="feedbackBackAttention">
|
|
检测到为保存内容,离开将丢失修改,请选择是否保留此次编辑?
|
|
</div>
|
|
<div class="feedbackBackBtnGroup">
|
|
<el-button class="feedbackBackBtn nosave" plain @click="feedbackBackCancel" type="primary">不保留</el-button>
|
|
<el-button class="feedbackBackBtn save" @click="feedbackBackConfirm" type="primary">保留</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="feedbackContentOverLengthDialogVisible" class="save-dialog">
|
|
<div class="feedbackContentOverLengthTitle">
|
|
温馨提示
|
|
</div>
|
|
<div class="feedbackContentOverLengthContent">
|
|
当前输入字数已达上限!
|
|
</div>
|
|
<div class="feedbackBackBtnGroup">
|
|
<el-button class="feedbackContentOverLengthBtn confirm" type="primary"
|
|
@click="feedbackContentOverLengthConfirm">确认</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="submitSuccessDialogVisible" class="save-dialog">
|
|
<div class="imgLine">
|
|
<img class="dialogImg" :src="success" alt="成功">
|
|
</div>
|
|
<div class="feedbackSuccessTitle">
|
|
提交成功
|
|
</div>
|
|
<div class="feedbackBackAttention">
|
|
——感谢您的反馈——
|
|
</div>
|
|
<div class="feedbackBackBtnGroup">
|
|
<el-button class="feedbackBackBtn confirm" @click="submitSuccessConfirm" type="primary">确定</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
<el-dialog v-model="submitFailureDialogVisible" class="save-dialog">
|
|
<div class="imgLine">
|
|
<img class="dialogImg" :src="failure" alt="失败">
|
|
</div>
|
|
<div class="feedbackFailureTitle">
|
|
提交失败
|
|
</div>
|
|
<div class="feedbackBackAttention">
|
|
{{ submitFailureContent }}
|
|
</div>
|
|
<div class="feedbackBackBtnGroup">
|
|
<el-button class="feedbackBackBtn confirm" @click="submitFailureConfirm" type="primary">确定</el-button>
|
|
</div>
|
|
</el-dialog>
|
|
|
|
</template>
|
|
|
|
<style scoped>
|
|
|
|
.backImg{
|
|
width: 40px;
|
|
height: 40px;
|
|
margin-left: 10px;
|
|
}
|
|
|
|
.el-container {
|
|
display: flex;
|
|
flex-direction: column;
|
|
overflow: auto;
|
|
}
|
|
|
|
.el-header {
|
|
height: auto;
|
|
padding: 0;
|
|
}
|
|
|
|
.el-main {
|
|
height: auto;
|
|
padding: 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: 20px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.card {
|
|
background-color: white;
|
|
padding: 20px;
|
|
height: auto;
|
|
border-radius: 15px;
|
|
}
|
|
|
|
.header-item {
|
|
margin: 10px 0;
|
|
}
|
|
|
|
.feedbackImgClass {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
margin: 0 20px;
|
|
}
|
|
|
|
.img {
|
|
max-width: 50%;
|
|
height: auto;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.feedbackSubmitBtn {
|
|
width: 60%;
|
|
height: 50px;
|
|
text-align: center;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 auto;
|
|
background: linear-gradient(90deg, #cac4fe, #b9d0fc, #a7dbfc);
|
|
border-radius: 60px;
|
|
|
|
color: #4423FF;
|
|
font-weight: bold;
|
|
font-size: 25px;
|
|
|
|
cursor: pointer;
|
|
|
|
}
|
|
|
|
.feedbackTitle {
|
|
font-size: 25px;
|
|
font-weight: bold;
|
|
|
|
}
|
|
|
|
.feedbackContent {
|
|
font-size: 20px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.feedbackTitle {
|
|
font-size: 20px;
|
|
}
|
|
|
|
.feedbackContent {
|
|
font-size: 15px;
|
|
}
|
|
}
|
|
|
|
.noFeedback {
|
|
margin: 20px 0;
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
}
|
|
|
|
.noFeedbackImg {
|
|
width: 200px;
|
|
height: 200px;
|
|
}
|
|
|
|
|
|
|
|
.feedbackBackTitle {
|
|
width: 100%;
|
|
text-align: center;
|
|
font-size: 25px;
|
|
font-weight: bold;
|
|
color: #2961FF
|
|
}
|
|
|
|
.feedbackBackAttention {
|
|
font-size: 15px;
|
|
font-weight: bold;
|
|
margin: 10px 5px;
|
|
text-align: center;
|
|
}
|
|
|
|
.feedbackBackBtnGroup {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 20px auto;
|
|
width: 75%;
|
|
}
|
|
|
|
.feedbackBackBtn {
|
|
margin: 0 auto;
|
|
font-weight: bold;
|
|
border-radius: 20px;
|
|
}
|
|
|
|
.save {
|
|
background: #816CF6;
|
|
border: none;
|
|
}
|
|
|
|
.nosave {
|
|
color: #816CF6;
|
|
background: white;
|
|
border: none;
|
|
}
|
|
|
|
.confirm {
|
|
background: #816CF6;
|
|
border: none;
|
|
}
|
|
|
|
.feedbackContentOverLengthTitle {
|
|
font-size: 25px;
|
|
font-weight: bold;
|
|
width: 100%;
|
|
text-align: center;
|
|
margin: 20px 0;
|
|
color: #2961FF;
|
|
}
|
|
|
|
.feedbackContentOverLengthContent {
|
|
font-size: 15px;
|
|
font-weight: bold;
|
|
width: 100%;
|
|
text-align: center;
|
|
margin: 20px 0;
|
|
}
|
|
|
|
.imgLine {
|
|
width: 100%;
|
|
display: flex;
|
|
}
|
|
|
|
.dialogImg {
|
|
max-width: 300px;
|
|
width: 50%;
|
|
height: 50%;
|
|
margin: 0 auto;
|
|
}
|
|
|
|
.feedbackSuccessTitle {
|
|
width: 100%;
|
|
text-align: center;
|
|
font-size: 25px;
|
|
font-weight: bold;
|
|
color: #2961FF
|
|
}
|
|
|
|
.feedbackFailureTitle {
|
|
width: 100%;
|
|
text-align: center;
|
|
font-size: 25px;
|
|
font-weight: bold;
|
|
color: #ff4646
|
|
}
|
|
|
|
.purpleDot {
|
|
margin: 0px 5px 0px 0px;
|
|
width: 20px;
|
|
height: 20px;
|
|
}
|
|
|
|
.feedbackHistoryTitle {
|
|
display: flex;
|
|
}
|
|
|
|
.feedbackSuccess {
|
|
margin-left: auto;
|
|
display: flex;
|
|
|
|
}
|
|
|
|
.feedbackSuccessWord {
|
|
padding: 3px 0 0 0;
|
|
color: #4221FF;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.feedbackSuccessImg {
|
|
width: 30px;
|
|
height: auto;
|
|
margin: 0 5px;
|
|
}
|
|
|
|
.feedbackHistoryContent {
|
|
min-height: 50px;
|
|
margin: 0 0 0 25px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.feedbackHistoryImg {
|
|
display: flex;
|
|
margin: 0px 0px 0px 20px;
|
|
}
|
|
|
|
.feedbackHistoryImgItem {
|
|
width: 100px;
|
|
height: auto;
|
|
margin: 5px 10px;
|
|
}
|
|
</style>
|
|
<style>
|
|
.uploadImg .el-upload {
|
|
width: 150px;
|
|
height: 150px;
|
|
}
|
|
|
|
@media (max-width: 768px) {
|
|
.uploadImg .el-upload {
|
|
width: 100px;
|
|
height: 100px;
|
|
}
|
|
}
|
|
|
|
.feedbackContentOverLengthBtn {
|
|
margin: 0 auto;
|
|
color: white;
|
|
|
|
&:hover,
|
|
&:active,
|
|
&:focus {
|
|
color: white !important;
|
|
}
|
|
}
|
|
|
|
.save-dialog {
|
|
background: linear-gradient(90deg, #cac4fe, #b9d0fc, #a7dbfc);
|
|
border-radius: 20px;
|
|
}
|
|
</style>
|