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.
 
 
 

679 lines
16 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);
const token = localStorage.getItem("localToken");
if (feedbackContent.value == "" && feedbackFileList.value.length == 0) {
submitFailureDialogVisible.value = true;
submitFailureContent.value = "请输入反馈内容或上传图片";
} else if (!token) {
submitFailureDialogVisible.value = true;
submitFailureContent.value = "token已失效,请重新登录!";
} 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: token,
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>