|
|
<template> <view class="main"> <view class="top" :style="{height:iSMT+'px'}"></view>
<!-- 头部导航 --> <view class="header"> <view class="back-icon"> <image @click="onBack" src="/static/customer-service-platform/cs-platform-back.png" class="header-icon-image"></image> </view> <view class="title">{{headerTitle}}</view> <view class="notification-icon"> <image src="/static/customer-service-platform/message.png" class="header-icon-image"></image> </view> </view> <!-- 内容区域 - 使用滚动视图 --> <scroll-view scroll-y class="content-container"> <view class="content-header"> <view class="content-header-area"> <view class="logo"> <image mode="aspectFit" src="/static/customer-service-platform/ellipse-dc-img.png"></image> </view> <view class="greeting"> <text class="greet-title">嗨,我能为你做点什么?</text> <text class="greet-sub">DeepChart随时为您提供服务</text> </view> </view> </view> <!--猜你想问卡片部分--> <view class="card"> <view class="suggest-header"> <text class="suggest-title">猜你想问</text> <view class="swap" @click="getQuestionList()"> <image class="swap-icon" src="/static/customer-service-platform/refresh-icon.png"></image> <text class="swap-title">换一换</text> </view> </view> <view class="card-line"></view> <view class="suggest-list"> <view class="suggest-item" v-for="(q, idx) in showQuestions" :key="idx" @click="onQuestionClick(q)"> <view class="left"> <view :class="['num', 'num-' + ((idx % 5) + 1)]">{{ idx + 1 }}</view> <text class="q-text">{{ q }}</text> </view> <view class="right"> <text class="arrow">›</text> </view> </view> </view> </view> <!--反馈卡片部分--> <text class="feedback-card-title">反馈中心</text> <view class="card"> <view class="suggest-header"> <text class="feedback-title">填写反馈内容</text> </view> <view class="card-line"></view> <textarea class="feedback-input" placeholder="请描述您想反馈的内容 最多可输入200字" maxlength="200" v-model="feedbackText" /> <view class="meta-row"> <text class="char-count">{{ feedbackText.length }}/200</text> </view> <view class="suggest-header"> <text class="upload-img-tip">上传图片</text> </view> <view class="upload-row"> <view class="img-slot" v-for="(img, index) in images" :key="index"> <image :src="img" mode="scaleToFill" class="slot-img" /> <button v-if="img" class="remove" @click="removeImage(index)">×</button> </view> <view class="img-slot" v-if="images.length < 3"> <view class="slot-empty" @click="chooseImage()"> <image src="/static/customer-service-platform/camera.png" class="camera-icon" /> </view> </view> <text class="tip-text" v-if="images.length === 0">最多添加3张图片</text> </view>
<button class="feedback-btn" @click="onSumbitFeedback()">提交</button> <feedback-modal ref="feedback" @confirm="onConfirm" /> </view> <!--历史反馈卡片部分--> <view class="card"> <text class="feedback-title">历史反馈内容</text> <view class="card-line"></view> <button class="feedback-btn" @click="viewHistory">查看</button> </view> </scroll-view> </view></template>
<script> import { getQuestionApi, addFeedbackRecordApi, uploadImageApi } from "../../api/customerServicePlatform/customerServicePlatform";
import FeedbackModal from '@/components/FeedbackModal.vue' export default { components: { FeedbackModal }, data() { return { headerTitle: '智能客服中台', iSMT: 0, questions: [ "DeepChart 有免费功能和付费功能的区分吗?具体有哪些?", "如何参与平台的用户反馈活动?反馈的问题会被采纳吗?", "我的自选股最多能添加多少只?能否按市场分类管理?", "注册时必须提供手机号 / 邮箱吗?能否匿名使用?", "忘记登录密码了,如何找回?", '如何注册账号?', '为什么无法注册账户?' ], showQuestions: [], feedbackText: '', images: [], } }, mounted() { // 状态栏高度
this.iSMT = uni.getSystemInfoSync().statusBarHeight; this.getQuestionList() }, created() {
}, methods: { onSuccess() { this.$refs.feedback.show({ status: 'success', title: '提交成功', subtitle: '— 感谢您的反馈 —', buttonText: '确定', width: '80%', }); }, onFail() { this.$refs.feedback.show({ status: 'fail', title: '提交失败', subtitle: '— 请重新提交 —', buttonText: '确定', width: '80%', }); }, onBack() { if (typeof uni !== 'undefined') uni.navigateBack(); }, async getQuestionList() { const res = await getQuestionApi() console.log(res) if (res.code == 200) { this.showQuestions = res.data }
}, onQuestionClick(q) { if (typeof uni !== 'undefined') uni.navigateTo({ url: `/pages/customerServicePlatform/questionDetail?question=${encodeURIComponent(q)}` }); }, chooseImage() { const that = this; if (typeof uni === 'undefined' || !uni.chooseImage) return;
const remain = 3 - (that.images ? that.images.length : 0); if (remain <= 0) { if (typeof uni !== 'undefined') uni.showToast({ title: '最多只能上传3张', icon: 'none' }); return; }
uni.chooseImage({ count: remain, sizeType: ['original', 'compressed'], sourceType: ['album', 'camera'], success(res) { const paths = res.tempFilePaths || (res.tempFiles && res.tempFiles.map(f => f.path)) || []; for (let p of paths) { if (that.images.length < 3) { that.images.push(p); } } }, fail(err) { uni.showToast({ title: `选择图片失败`, icon: 'none' }); } }); },
removeImage(index) { // 删除并保持响应
this.images.splice(index, 1); }, async onSumbitFeedback() { if (!this.feedbackText.trim()) { if (typeof uni !== 'undefined') uni.showToast({ title: '请填写反馈内容', icon: 'none' }); return; } if (typeof uni !== 'undefined') uni.showLoading({ title: '提交中...' }); try { let uploadedImages = []; let imgFlag = true for (let i = 0; i < this.images.length; i++) { const f = this.images[i]; await new Promise((resolve, reject) => { uni.getImageInfo({ src: f, success: () => resolve(), fail: reject }); }); const uploadRes = await new Promise((resolve, reject) => { uni.uploadFile({ url: 'http://39.101.133.168:8828/hljw/api/aws/upload', filePath: f, name: 'file', formData: { dir: 'deepchart' }, success: (res) => { try { const data = JSON.parse(res.data); if (data.code === 200) { uploadedImages.push(data.data.url); resolve(data); } else { uni.showToast({ title: `第${i + 1}张图片上传失败`, icon: 'none' }); imgFlag = false; reject(data); } } catch (err) { imgFlag = false; reject(err); } }, fail: (err) => { imgFlag = false; uni.showToast({ title: `第${i + 1}张图片上传失败`, icon: 'none' }); reject(err); } }); }); } if (!imgFlag) { return } const [image1 = '', image2 = '', image3 = ''] = uploadedImages; const res = await addFeedbackRecordApi({ token: "a1bef735d336831ccb0cc3f532093b60", content: this.feedbackText, image1, image2, image3 }) if (res.code == 200) { this.onSuccess() } else { this.onFail() } } catch { this.onFail() } finally { uni.hideLoading(); this.feedbackText = ''; this.images = []; } }, viewHistory() { // 跳转到历史页
if (typeof uni !== 'undefined') uni.navigateTo({ url: '/pages/customerServicePlatform/historyRecord' }); } } }</script>
<style scoped> .main { display: flex; flex-direction: column; height: 100vh; background-color: #ffffff; }
.header { display: flex; justify-content: space-between; align-items: center; padding: 20rpx 30rpx; background-color: #ffffff; }
.title { color: #000000; text-align: center; font-size: 32rpx; font-style: normal; font-weight: 400; }
.back-icon, .notification-icon { width: 40rpx; display: flex; align-items: center; justify-content: center; }
.header-icon-image { width: 40rpx; height: 40rpx; object-fit: contain; }
.content-container { padding: 20rpx; width: 100%; box-sizing: border-box; overflow-x: hidden; }
.content-header { display: flex; align-items: center; justify-content: center; gap: 24rpx; padding: 0 60rpx; width: 100%; box-sizing: border-box; height: 188rpx; }
.content-header-area { display: flex; gap: 20rpx; }
.logo { width: 120rpx; height: 120rpx; display: flex; align-items: center; justify-content: center; flex: 0 0 112rpx; }
.greeting { display: flex; flex-direction: column; justify-content: center; flex: 1 1 auto; }
.greet-title { color: #000; font-size: 40rpx; font-style: normal; font-weight: 500; line-height: normal; margin: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.greet-sub { color: #838383; font-size: 28rpx; font-style: normal; font-weight: 400; line-height: normal; margin-top: 12rpx; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.card { width: 90%; margin: 0 auto; border-radius: 16rpx; padding: 20rpx 40rpx; box-sizing: border-box; border-radius: 12rpx; border: 4rpx solid #FCC8D4; background: linear-gradient(180deg, #FCC8D3 0%, #FEF0F3 30%, #FFF 100%); margin-bottom: 20rpx; }
.suggest-header { width: 100%; display: flex; align-items: center; justify-content: space-between; }
.suggest-title { color: #000000; font-size: 32rpx; font-style: normal; font-weight: 400; line-height: normal; }
.swap { display: flex; align-items: center; transition: transform 0.1s ease, background-color 0.1s ease; }
.swap:active { transform: scale(0.95); }
.swap-icon { width: 30rpx; height: 30rpx; }
.swap-title { padding-left: 8rpx; color: #000000; font-size: 24rpx; font-style: normal; font-weight: 400; line-height: normal; }
.suggest-list { margin-top: 20rpx; }
.card-line { margin-top: 20rpx; width: 100%; height: 2rpx; border-radius: 2rpx; background: #FFF; }
.suggest-item { display: flex; justify-content: space-between; align-items: center; padding-top: 10rpx; border-radius: 12rpx; margin-bottom: 20rpx; width: 100%; box-sizing: border-box; }
.left { width: 90%; display: flex; align-items: center; }
.num { font-size: 40rpx; font-style: normal; font-weight: 700; line-height: normal; }
.num-1 { color: #df5662; }
.num-2 { color: #ec6d4f; }
.num-3 { color: #f3ba40; }
.num-4 { color: #9296a0; }
.num-5 { color: #9296a0; }
.q-text { padding-left: 14rpx; display: block; color: #333; font-size: 28rpx; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.right { width: 48rpx; display: flex; align-items: center; justify-content: flex-end; }
.arrow { color: #cfcfcf; font-size: 36rpx; }
.suggest-item:active { background: rgba(255, 77, 128, 0.06); }
.feedback-card-title { display: flex; justify-content: center; color: #000000; font-size: 32rpx; font-weight: 700; line-height: 40rpx; width: 100%; margin-bottom: 20rpx; }
.feedback-title { color: #000000; font-size: 32rpx; font-style: normal; font-weight: 400; line-height: normal; }
.feedback-input { width: 100%; display: flex; padding: 20rpx; flex-direction: column; box-sizing: border-box; align-items: flex-start; gap: 12rpx; align-self: stretch; border-radius: 12rpx; border: 2rpx solid #F0F1F1; margin-top: 20rpx; display: flex; background: #FFF; color: #8a8a8a; font-size: 24rpx; font-weight: 700; line-height: normal; }
.meta-row { display: flex; justify-content: flex-end; margin-top: 12rpx; }
.char-count { color: #999 }
.upload-img-tip { color: #000000; font-size: 24rpx; font-style: normal; font-weight: 400; line-height: normal; }
.upload-row { display: flex; justify-content: flex-start; align-items: flex-start; align-content: flex-start; flex-wrap: wrap; gap: 20rpx; margin-top: 20rpx; width: 100%; }
.img-slot { width: calc((100% - 2 * 30rpx) / 3); aspect-ratio: 1 / 1; border-radius: 6px; border: 1px solid #F0F1F1; background: #FFF; position: relative; display: flex; align-items: center; justify-content: center; overflow: hidden; transition: transform 0.2s ease; }
.slot-empty { width: 100%; height: 100%; display: flex; align-items: center; justify-content: center; }
.camera-icon { width: 34rpx; height: 34rpx; }
.slot-img { width: 100%; height: 100%; border-radius: 16rpx; }
.remove { position: absolute; right: 6rpx; top: 6rpx; border-radius: 50%; background: #fd5c58; padding: 0; color: #fff; width: 36rpx; height: 36rpx; font-size: 28rpx; line-height: 36rpx; text-align: center; border: none; outline: none; cursor: pointer; }
.remove:active { background: rgba(0, 0, 0, 0.75); }
.image-upload-tip { display: flex; align-items: center; }
.tip-text { color: #999999; font-size: 24rpx; font-style: normal; font-weight: 400; line-height: 40rpx; padding-top: 64rpx; }
.feedback-btn { margin-top: 24rpx; width: 180rpx; height: 60rpx; aspect-ratio: 89/30; border-radius: 30rpx; background: #090A08; color: #ffffff; display: flex; justify-content: center; align-items: center; font-size: 32rpx; font-style: normal; font-weight: 700; line-height: normal; }</style>
|