434 lines
11 KiB
Vue
434 lines
11 KiB
Vue
<template>
|
||
<view class="settings-screen">
|
||
<view class="settings-bg"></view>
|
||
<!-- 状态栏占位 -->
|
||
<view class="status-bar-placeholder"></view>
|
||
|
||
<!-- Header -->
|
||
<view class="settings-header">
|
||
<view class="settings-back-btn" @click="handleBack">
|
||
<text class="settings-back-icon">‹</text>
|
||
</view>
|
||
<text class="settings-title">设置与反馈</text>
|
||
<view class="settings-header-placeholder"></view>
|
||
</view>
|
||
|
||
<!-- Content -->
|
||
<scroll-view scroll-y class="settings-content">
|
||
<view class="settings-content-inner">
|
||
|
||
<!-- Section 1: 偏好设置 -->
|
||
<!-- <view class="settings-section">
|
||
<view class="settings-item settings-item-border">
|
||
<view class="settings-item-left">
|
||
<text class="settings-item-icon">🔔</text>
|
||
<text class="settings-item-label">推送通知</text>
|
||
</view>
|
||
<view class="settings-switch" :class="{ 'settings-switch-active': pushEnabled }"
|
||
@click="togglePush">
|
||
<view class="settings-switch-thumb"
|
||
:class="{ 'settings-switch-thumb-active': pushEnabled }"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<view class="settings-item">
|
||
<view class="settings-item-left">
|
||
<text class="settings-item-icon">🔊</text>
|
||
<text class="settings-item-label">音效反馈</text>
|
||
</view>
|
||
<view class="settings-switch" :class="{ 'settings-switch-active': soundEnabled }"
|
||
@click="toggleSound">
|
||
<view class="settings-switch-thumb"
|
||
:class="{ 'settings-switch-thumb-active': soundEnabled }"></view>
|
||
</view>
|
||
</view>
|
||
</view> -->
|
||
|
||
<!-- Section 2: 支持 -->
|
||
<view class="settings-section">
|
||
<view class="settings-item settings-item-border settings-item-clickable" @click="handleFeedback">
|
||
<view class="settings-item-left">
|
||
<text class="settings-item-icon">💬</text>
|
||
<text class="settings-item-label">意见反馈</text>
|
||
</view>
|
||
<text class="settings-item-arrow">›</text>
|
||
</view>
|
||
|
||
<view class="settings-item settings-item-border settings-item-clickable" @click="handleFAQ">
|
||
<view class="settings-item-left">
|
||
<text class="settings-item-icon">❓</text>
|
||
<text class="settings-item-label">常见问题</text>
|
||
</view>
|
||
<text class="settings-item-arrow">›</text>
|
||
</view>
|
||
|
||
<view class="settings-item settings-item-clickable" @click="handlePrivacy">
|
||
<view class="settings-item-left">
|
||
<text class="settings-item-icon">🛡️</text>
|
||
<text class="settings-item-label">隐私政策</text>
|
||
</view>
|
||
<text class="settings-item-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- Section 3: 快速反馈 -->
|
||
<view class="settings-feedback-section">
|
||
<text class="settings-feedback-title">快速反馈</text>
|
||
<textarea class="settings-feedback-textarea" v-model="feedbackText" placeholder="您遇到的问题或建议..."
|
||
:maxlength="500" />
|
||
<view class="settings-feedback-btn" @click="submitFeedback">
|
||
<text class="settings-feedback-btn-text">提交反馈</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 退出登录 -->
|
||
<view class="settings-logout-btn" @click="handleLogout">
|
||
<text class="settings-logout-text">退出登录</text>
|
||
</view>
|
||
|
||
<!-- 版本信息 -->
|
||
<view class="settings-version">
|
||
<text class="settings-version-text">当前版本 v1.0.2</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="ts">
|
||
import { ref } from "vue";
|
||
import { userApi } from "@/api";
|
||
import { logout } from "@/utils/auth";
|
||
|
||
declare const uni: any;
|
||
|
||
const emit = defineEmits<{
|
||
back: [];
|
||
navigate: [screen: string];
|
||
}>();
|
||
|
||
const pushEnabled = ref(true);
|
||
const soundEnabled = ref(true);
|
||
const feedbackText = ref("");
|
||
|
||
const togglePush = () => {
|
||
pushEnabled.value = !pushEnabled.value;
|
||
uni.showToast({
|
||
title: pushEnabled.value ? "已开启推送通知" : "已关闭推送通知",
|
||
icon: "none"
|
||
});
|
||
};
|
||
|
||
const toggleSound = () => {
|
||
soundEnabled.value = !soundEnabled.value;
|
||
uni.showToast({
|
||
title: soundEnabled.value ? "已开启音效反馈" : "已关闭音效反馈",
|
||
icon: "none"
|
||
});
|
||
};
|
||
|
||
const handleFeedback = () => {
|
||
emit('navigate', 'feedback');
|
||
};
|
||
|
||
const handleFAQ = () => {
|
||
emit('navigate', 'faq');
|
||
};
|
||
|
||
const handlePrivacy = () => {
|
||
emit('navigate', 'privacy');
|
||
};
|
||
|
||
const submitFeedback = async () => {
|
||
if (!feedbackText.value.trim()) {
|
||
uni.showToast({ title: "请输入反馈内容", icon: "none" });
|
||
return;
|
||
}
|
||
|
||
try {
|
||
await userApi.submitFeedback({
|
||
content: feedbackText.value.trim(),
|
||
feedback_type: 'other'
|
||
});
|
||
uni.showToast({ title: "感谢您的反馈!", icon: "success" });
|
||
feedbackText.value = "";
|
||
} catch (error: any) {
|
||
uni.showToast({
|
||
title: error.msg || "提交失败,请稍后重试",
|
||
icon: "none"
|
||
});
|
||
}
|
||
};
|
||
|
||
const handleLogout = () => {
|
||
// Web 环境使用 confirm,uni-app 环境使用 showModal
|
||
if (typeof uni?.showModal === "function") {
|
||
uni.showModal({
|
||
title: "提示",
|
||
content: "确定要退出登录吗?",
|
||
success: (res: any) => {
|
||
if (res.confirm) {
|
||
logout();
|
||
uni.showToast({ title: "已退出登录", icon: "success" });
|
||
}
|
||
},
|
||
});
|
||
} else {
|
||
const confirmed = confirm("确定要退出登录吗?");
|
||
if (confirmed) {
|
||
logout();
|
||
if (typeof uni?.showToast === "function") {
|
||
uni.showToast({ title: "已退出登录", icon: "success" });
|
||
}
|
||
}
|
||
}
|
||
};
|
||
|
||
const handleBack = () => {
|
||
emit('back');
|
||
};
|
||
</script>
|
||
|
||
<style scoped>
|
||
.settings-screen {
|
||
height: 100%;
|
||
display: flex;
|
||
flex-direction: column;
|
||
background-color: #f0efe9;
|
||
position: relative;
|
||
}
|
||
|
||
.status-bar-placeholder {
|
||
height: var(--status-bar-height, 0);
|
||
width: 100%;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.settings-bg {
|
||
position: absolute;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
pointer-events: none;
|
||
opacity: 0.3;
|
||
background-image: url("https://www.transparenttextures.com/patterns/rice-paper.png");
|
||
}
|
||
|
||
/* Header */
|
||
.settings-header {
|
||
position: relative;
|
||
z-index: 10;
|
||
height: 88rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 0 32rpx;
|
||
border-bottom: 1rpx solid #dcd3c9;
|
||
background-color: rgba(253, 251, 247, 0.8);
|
||
backdrop-filter: blur(10rpx);
|
||
}
|
||
|
||
.settings-back-btn {
|
||
width: 64rpx;
|
||
height: 64rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
background: transparent;
|
||
border: none;
|
||
padding: 0;
|
||
margin-left: -16rpx;
|
||
}
|
||
|
||
.settings-back-icon {
|
||
font-size: 48rpx;
|
||
color: #5a5a5a;
|
||
font-weight: 300;
|
||
}
|
||
|
||
.settings-title {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #2c2c2c;
|
||
letter-spacing: 0.2em;
|
||
}
|
||
|
||
.settings-header-placeholder {
|
||
width: 64rpx;
|
||
}
|
||
|
||
/* Content */
|
||
.settings-content {
|
||
flex: 1;
|
||
height: 0;
|
||
position: relative;
|
||
z-index: 10;
|
||
}
|
||
|
||
.settings-content-inner {
|
||
padding: 32rpx;
|
||
}
|
||
|
||
/* Section */
|
||
.settings-section {
|
||
background-color: #fffdf9;
|
||
border-radius: 24rpx;
|
||
border: 1rpx solid #e5e5e5;
|
||
overflow: hidden;
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.settings-item {
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: space-between;
|
||
padding: 24rpx 32rpx;
|
||
}
|
||
|
||
.settings-item-border {
|
||
border-bottom: 1rpx solid #f0f0f0;
|
||
}
|
||
|
||
.settings-item-clickable {
|
||
transition: background-color 0.2s;
|
||
}
|
||
|
||
.settings-item-clickable:active {
|
||
background-color: #fafafa;
|
||
}
|
||
|
||
.settings-item-left {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
}
|
||
|
||
.settings-item-icon {
|
||
font-size: 32rpx;
|
||
}
|
||
|
||
.settings-item-label {
|
||
font-size: 28rpx;
|
||
color: #2c2c2c;
|
||
}
|
||
|
||
.settings-item-arrow {
|
||
font-size: 32rpx;
|
||
color: #ccc;
|
||
}
|
||
|
||
/* Switch */
|
||
.settings-switch {
|
||
width: 80rpx;
|
||
height: 40rpx;
|
||
border-radius: 40rpx;
|
||
background-color: #ccc;
|
||
position: relative;
|
||
transition: background-color 0.3s;
|
||
}
|
||
|
||
.settings-switch-active {
|
||
background-color: #8b2323;
|
||
}
|
||
|
||
.settings-switch-thumb {
|
||
position: absolute;
|
||
top: 4rpx;
|
||
left: 4rpx;
|
||
width: 32rpx;
|
||
height: 32rpx;
|
||
border-radius: 50%;
|
||
background-color: #fff;
|
||
box-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.2);
|
||
transition: left 0.3s;
|
||
}
|
||
|
||
.settings-switch-thumb-active {
|
||
left: 44rpx;
|
||
}
|
||
|
||
/* Feedback Section */
|
||
.settings-feedback-section {
|
||
margin-bottom: 32rpx;
|
||
}
|
||
|
||
.settings-feedback-title {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: #8b2323;
|
||
margin-bottom: 16rpx;
|
||
display: block;
|
||
padding: 0 8rpx;
|
||
}
|
||
|
||
.settings-feedback-textarea {
|
||
width: 100%;
|
||
height: 192rpx;
|
||
background-color: #fffdf9;
|
||
border: 1rpx solid #e5e5e5;
|
||
border-radius: 24rpx;
|
||
padding: 24rpx;
|
||
font-size: 28rpx;
|
||
color: #2c2c2c;
|
||
box-sizing: border-box;
|
||
}
|
||
|
||
.settings-feedback-btn {
|
||
width: 100%;
|
||
margin-top: 16rpx;
|
||
padding: 24rpx 0;
|
||
background-color: #2c2c2c;
|
||
border-radius: 16rpx;
|
||
border: none;
|
||
display: flex;
|
||
justify-content: center;
|
||
}
|
||
|
||
.settings-feedback-btn-text {
|
||
font-size: 24rpx;
|
||
font-weight: 700;
|
||
color: #f2e6d8;
|
||
}
|
||
|
||
/* Logout Button */
|
||
.settings-logout-btn {
|
||
width: 100%;
|
||
padding: 24rpx 0;
|
||
background-color: #fffdf9;
|
||
border: 1rpx solid #e5e5e5;
|
||
border-radius: 24rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 16rpx;
|
||
margin-bottom: 32rpx;
|
||
transition: background-color 0.2s;
|
||
}
|
||
|
||
.settings-logout-btn:active {
|
||
background-color: #fff5f5;
|
||
}
|
||
|
||
.settings-logout-icon {
|
||
font-size: 28rpx;
|
||
}
|
||
|
||
.settings-logout-text {
|
||
font-size: 28rpx;
|
||
font-weight: 700;
|
||
color: #8b2323;
|
||
}
|
||
|
||
/* Version */
|
||
.settings-version {
|
||
text-align: center;
|
||
padding: 32rpx 0;
|
||
}
|
||
|
||
.settings-version-text {
|
||
font-size: 20rpx;
|
||
color: #ccc;
|
||
}
|
||
</style>
|