Files
----/前端源码/uni-app/components/screens/ProfileSettings.vue

434 lines
11 KiB
Vue
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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.
<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 环境使用 confirmuni-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>