Files
jiapuapp/pages/profile/m07-feedback.vue
T
2026-07-21 20:59:10 +08:00

54 lines
4.8 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 页面编号M-07用途提交意见反馈 -->
<template>
<view class="feedback-page" :class="{ 'feedback-state--ready': feedbackState === 'ready', 'feedback-state--submitting': feedbackState === 'submitting' }">
<ModulePageBackground module="profile" />
<view class="page-layer"><PageHeader title="意见反馈" /></view>
<view class="page-content page-layer">
<text class="lead">你的建议会帮助我们把家谱做得更好</text>
<view class="type-grid">
<view v-for="type in feedbackTypes" :key="type" class="type-chip" :class="{ active: feedbackForm.type === type }" role="button" @click="feedbackForm.type = type; errors.type = ''">{{ type }}</view>
</view>
<text v-if="errors.type" class="field-error">{{ errors.type }}</text>
<view class="form-panel">
<textarea v-model.trim="feedbackForm.description" auto-height maxlength="500" aria-label="问题描述" placeholder="请说明遇到的问题、操作步骤或建议" @input="errors.description = ''" />
<text class="counter">{{ feedbackForm.description.length }}/500</text>
<text v-if="errors.description" class="field-error">{{ errors.description }}</text>
<view class="contact-row"><text>联系方式</text><input v-model.trim="feedbackForm.contact" maxlength="50" aria-label="联系方式" placeholder="手机号或邮箱(选填)" /></view>
</view>
<text class="privacy-note">仅用于跟进本次反馈不会在家谱中公开</text>
<AppButton block :disabled="feedbackState === 'submitting'" :label="feedbackState === 'submitting' ? '正在提交' : '提交反馈'" @click="submitFeedback" />
</view>
<AppToast :visible="toastVisible" :message="toastMessage" />
</view>
</template>
<script setup>
import { onUnmounted, reactive, ref } from "vue";
import AppButton from "@/components/AppButton.vue";
import AppToast from "@/components/AppToast.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
const feedbackTypes = ["功能问题", "使用建议", "内容纠错", "其他"];
const feedbackForm = reactive({ type: "", description: "", contact: "" });
const errors = reactive({ type: "", description: "" });
const feedbackState = ref("ready");
const toastVisible = ref(false); const toastMessage = ref(""); let timer = null;
const validateFeedback = () => {
errors.type = feedbackForm.type ? "" : "请选择反馈类型";
errors.description = feedbackForm.description.length < 5 ? "请至少填写 5 个字的问题描述" : "";
return !errors.type && !errors.description;
};
const submitFeedback = () => {
if (!validateFeedback() || feedbackState.value === "submitting") return;
feedbackState.value = "submitting";
timer = setTimeout(() => { feedbackState.value = "ready"; feedbackForm.type = ""; feedbackForm.description = ""; feedbackForm.contact = ""; toastMessage.value = "反馈已保存,服务接入后将提交给家谱助手"; toastVisible.value = true; timer = setTimeout(() => (toastVisible.value = false), 2200); }, 500);
};
onUnmounted(() => clearTimeout(timer));
</script>
<style scoped lang="scss">
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
.feedback-page{display:flex;min-height:100vh;flex-direction:column;background:$paper}.page-layer{z-index:1}.page-content{flex:1;padding:26rpx 30rpx 72rpx}.lead{display:block;color:$ink-muted;font-size:23rpx;line-height:1.5;text-align:center}.type-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:14rpx;margin-top:20rpx}.type-chip{@include adaptive.adaptive-profile-field;display:flex;min-height:76rpx;align-items:center;justify-content:center;padding:10rpx 16rpx;color:$ink-muted;font-size:22rpx;text-align:center}.type-chip.active{color:$brand-red;font-weight:700;filter:saturate(1.2)}.form-panel{@include adaptive.adaptive-profile-content;margin-top:20rpx;padding:30rpx 34rpx}.form-panel textarea{display:block;width:auto;min-width:0;min-height:210rpx;color:$ink;font-size:24rpx;line-height:1.65}.counter{display:block;color:$ink-muted;font-size:20rpx;text-align:right}.contact-row{display:grid;grid-template-columns:130rpx minmax(0,1fr);min-height:88rpx;align-items:center;gap:16rpx;margin-top:16rpx;border-top:1px solid rgba(181,137,63,.38)}.contact-row text{color:$ink;font-size:23rpx;font-weight:700}.contact-row input{width:auto;min-width:0;min-height:68rpx;color:$ink;font-size:22rpx;text-align:right}.field-error{display:block;margin-top:7rpx;color:#b42318;font-size:20rpx;line-height:1.4;text-align:right}.privacy-note{display:block;margin-top:15rpx;color:$ink-muted;font-size:20rpx;line-height:1.5;text-align:center}.page-content>.app-button{margin-top:24rpx}@media(max-width:340px){.page-content{padding-right:22rpx;padding-left:22rpx}.form-panel{padding-right:26rpx;padding-left:26rpx}}
</style>