Files
guoxue-mp/pages/user/feedback.vue
T
2026-03-25 15:59:24 +08:00

260 lines
6.0 KiB
Vue

<template>
<view class="feedback-page">
<view class="top-header" :style="{ paddingTop: statusBarPadding }">
<u-icon name="arrow-left" size="32" color="#1e244f" @click="goBack"></u-icon>
<text class="header-title">意见反馈</text>
<view style="width:32rpx;height:32rpx;"></view>
</view>
<view class="feedback-card">
<view class="card-header">
<text class="card-title">意见反馈</text>
<text class="card-sub">多选</text>
</view>
<view class="section" v-for="group in feedbackOptions" :key="group.title">
<view class="section-title">{{ group.title }}</view>
<view class="option" v-for="option in group.options" :key="option.value" @tap="toggleOption(option)">
<view class="check" :class="{ active: option.selected }">
<view class="dot" v-if="option.selected"></view>
</view>
<text class="option-text">{{ option.label }}</text>
</view>
</view>
</view>
<view class="say-card">
<view class="say-header">
<text class="say-title">我还想说</text>
<text class="say-optional">选填</text>
</view>
<textarea
class="say-textarea"
placeholder="有了您的宝贵意见,我们才能变得更好哦~"
placeholder-style="color:#b4bad0"
v-model="extraMessage"
/>
</view>
<button class="submit-btn" @click="submitFeedback">提交反馈</button>
</view>
</template>
<script>
import {addFeedbackReq} from "@/api/common";
export default {
data() {
return {
statusBarPadding: '40rpx',
extraMessage: '',
feedbackOptions: [
{
title: '咨询体验',
options: [
{ label: '咨询过程不够流畅', value: 'flow' },
{ label: '咨询师答非所问', value: 'answer' },
{ label: '咨询结果不满意', value: 'result' },
{ label: '咨询耗费时间', value: 'time' },
{ label: '我对咨询体验过程无意见', value: 'noExperience' }
]
},
{
title: '功能体验',
options: [
{ label: '产品界面不够美观', value: 'ui' },
{ label: '不喜欢输入方式', value: 'input' },
{ label: '我对功能无意见', value: 'noFunction' }
]
}
]
}
},
onLoad() {
const info = uni.getSystemInfoSync()
this.statusBarPadding = `${(info.statusBarHeight || 20) + 10}px`
},
methods: {
goBack() {
uni.navigateBack().catch(() => {
uni.switchTab({ url: '/pages/user/index' })
})
},
toggleOption(option) {
this.$set(option, 'selected', !option.selected)
},
async submitFeedback() {
const advisory = []
const func = []
this.feedbackOptions.forEach(group => {
group.options.forEach(opt => {
if (opt.selected) {
if (group.title === '咨询体验') advisory.push(opt.label)
else if (group.title === '功能体验') func.push(opt.label)
}
})
})
if (!advisory.length && !func.length && !this.extraMessage.trim()) {
uni.showToast({ title: '请选择或填写反馈', icon: 'none' })
return
}
try {
await addFeedbackReq({
advisoryExp: advisory.join('、'),
funcExp: func.join('、'),
comments: this.extraMessage.trim()
})
uni.showToast({ title: '感谢反馈', icon: 'success' })
this.feedbackOptions.forEach(group => {
group.options.forEach(opt => (opt.selected = false))
})
this.extraMessage = ''
setTimeout(() => {
uni.navigateBack()
}, 1500)
} catch (error) {
const msg = error?.msg || error?.message || '提交失败,请稍后再试'
uni.showToast({title: msg, icon: 'none'})
}
}
}
}
</script>
<style lang="scss" scoped>
.feedback-page {
min-height: 100vh;
padding: 40rpx 30rpx 120rpx;
background: linear-gradient(180deg, #e8f2ff 0%, #f4f5ff 100%);
box-sizing: border-box;
}
.top-header {
display: flex;
align-items: center;
justify-content: space-between;
padding-bottom: 30rpx;
}
.header-title {
font-size: 32rpx;
color: #1e244f;
font-weight: 600;
}
.feedback-card {
background: rgba(255, 255, 255, 0.92);
border-radius: 30rpx;
padding: 30rpx;
box-shadow: 0 20rpx 50rpx rgba(149, 170, 255, 0.2);
}
.card-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20rpx;
}
.card-title {
font-size: 34rpx;
font-weight: 600;
color: #3b437a;
}
.card-sub {
font-size: 26rpx;
color: #b3b8d3;
}
.section {
margin-top: 20rpx;
}
.section-title {
font-size: 28rpx;
color: #9ea4c5;
margin-bottom: 12rpx;
}
.option {
display: flex;
align-items: center;
padding: 18rpx 0;
}
.check {
width: 32rpx;
height: 32rpx;
border-radius: 16rpx;
border: 2rpx solid #ccd0e6;
display: flex;
align-items: center;
justify-content: center;
margin-right: 20rpx;
}
.check.active {
border-color: #8d9cff;
background-color: #eef0ff;
}
.dot {
width: 16rpx;
height: 16rpx;
border-radius: 50%;
background: #7c8cff;
}
.option-text {
font-size: 28rpx;
color: #5a5f85;
}
.say-card {
margin-top: 30rpx;
padding: 30rpx;
background: rgba(255, 255, 255, 0.9);
border-radius: 30rpx;
box-shadow: 0 20rpx 50rpx rgba(149, 170, 255, 0.15);
}
.say-header {
display: flex;
justify-content: space-between;
margin-bottom: 20rpx;
}
.say-title {
font-size: 32rpx;
color: #3b437a;
}
.say-optional {
font-size: 26rpx;
color: #b3b8d3;
}
.say-textarea {
width: 100%;
min-height: 200rpx;
background: #f5f6fb;
border-radius: 20rpx;
padding: 20rpx;
box-sizing: border-box;
font-size: 28rpx;
color: #4c5277;
}
.submit-btn {
margin-top: 40rpx;
height: 96rpx;
line-height: 96rpx;
border-radius: 48rpx;
background: linear-gradient(120deg, #7c8cff, #9da6ff);
color: #fff;
font-size: 30rpx;
letter-spacing: 4rpx;
}
</style>