1037 lines
26 KiB
Plaintext
1037 lines
26 KiB
Plaintext
<!-- 个人设置页面 - UTSJSONObject 优化版本 -->
|
||
<template>
|
||
<scroll-view direction="vertical" class="settings-page" :scroll-y="true" :enable-back-to-top="true">
|
||
<!-- 头部 -->
|
||
<view class="settings-header">
|
||
<view class="header-content">
|
||
<view class="back-btn" @click="goBack">
|
||
<text class="back-icon">←</text>
|
||
</view>
|
||
<text class="header-title">{{ $t('mt.settings.profile') }}</text>
|
||
<view class="header-placeholder"></view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 用户信息区域 -->
|
||
<view class="user-section">
|
||
<view class="user-card">
|
||
<view class="user-avatar">
|
||
<text class="avatar-text">用</text>
|
||
</view>
|
||
<view class="user-info">
|
||
<text class="user-name">{{ userName }}</text>
|
||
<text class="user-email">{{ userEmail }}</text>
|
||
</view>
|
||
<view class="edit-btn" @click="editProfile">
|
||
<text class="edit-text">{{ $t('mt.button.edit') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 语言偏好设置 -->
|
||
<view class="settings-section">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ $t('mt.settings.language') }}</text>
|
||
</view>
|
||
<view class="setting-item" @click="showLanguageSelector">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.interfaceLanguage') }}</text>
|
||
<text class="item-value">{{ currentLanguageName }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item" @click="showPreferredLanguages">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.contentLanguage') }}</text>
|
||
<text class="item-value">{{ preferredLanguagesText }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.autoTranslate') }}</text>
|
||
<text class="item-desc">{{ $t('mt.settings.autoTranslateDesc') }}</text>
|
||
</view>
|
||
<view class="toggle-switch" :class="{ active: userPreferences.auto_translate }" @click="toggleAutoTranslate">
|
||
<view class="toggle-thumb"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 内容分类偏好 -->
|
||
<view class="settings-section">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ $t('mt.settings.contentPreference') }}</text>
|
||
</view>
|
||
<view class="setting-item" @click="showCategoryPreferences">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.categories') }}</text>
|
||
<text class="item-value">{{ preferredCategoriesText }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item" @click="showReadingMode">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.readingMode') }}</text>
|
||
<text class="item-value">{{ readingModeText }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item" @click="showFontSize">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.fontSize') }}</text>
|
||
<text class="item-value">{{ fontSizeText }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 通知设置 -->
|
||
<view class="settings-section">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ $t('mt.settings.notifications') }}</text>
|
||
</view>
|
||
<view class="setting-item">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.push') }}</text>
|
||
<text class="item-desc">{{ $t('mt.settings.pushDesc') }}</text>
|
||
</view>
|
||
<view class="toggle-switch" :class="{ active: userPreferences.notification_enabled }" @click="toggleNotification">
|
||
<view class="toggle-thumb"></view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- AI助手设置 -->
|
||
<view class="settings-section">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ $t('mt.settings.ai') }}</text>
|
||
</view>
|
||
<view class="setting-item" @click="clearChatHistory">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.clearChat') }}</text>
|
||
<text class="item-desc">{{ $t('mt.settings.clearChatDesc') }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item" @click="showAISettings">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.aiPreference') }}</text>
|
||
<text class="item-desc">{{ $t('mt.settings.aiPreferenceDesc') }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 数据与隐私 -->
|
||
<view class="settings-section">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ $t('mt.settings.privacy') }}</text>
|
||
</view>
|
||
<view class="setting-item" @click="exportData">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.exportData') }}</text>
|
||
<text class="item-desc">{{ $t('mt.settings.exportDataDesc') }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item" @click="clearUserData">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.clearUserData') }}</text>
|
||
<text class="item-desc">{{ $t('mt.settings.clearUserDataDesc') }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 关于 -->
|
||
<view class="settings-section">
|
||
<view class="section-header">
|
||
<text class="section-title">{{ $t('mt.settings.about') }}</text>
|
||
</view>
|
||
<view class="setting-item">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.version') }}</text>
|
||
<text class="item-value">v1.0.0</text>
|
||
</view>
|
||
</view>
|
||
<view class="setting-item" @click="showPrivacyPolicy">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.privacyPolicy') }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
<view class="setting-item" @click="showTermsOfService">
|
||
<view class="item-content">
|
||
<text class="item-label">{{ $t('mt.settings.terms') }}</text>
|
||
</view>
|
||
<text class="item-arrow">›</text>
|
||
</view>
|
||
</view>
|
||
</scroll-view>
|
||
|
||
<!-- 语言选择弹窗 -->
|
||
<view class="language-modal" v-if="showLanguageModal" @click="hideLanguageSelector">
|
||
<view class="language-content" @click.stop>
|
||
<view class="modal-header">
|
||
<text class="modal-title">{{ $t('mt.settings.selectLanguage') }}</text>
|
||
<view class="close-btn" @click="hideLanguageSelector">
|
||
<text class="close-text">✕</text>
|
||
</view>
|
||
</view>
|
||
<view class="language-list">
|
||
<view
|
||
v-for="language in availableLanguages"
|
||
:key="language.code"
|
||
class="language-item"
|
||
:class="{ active: currentLanguageCode === language.code }"
|
||
@click="selectLanguage(language.code)">
|
||
<text class="language-name">{{ language.name }}</text>
|
||
<text class="language-code">{{ language.code }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 内容语言偏好弹窗 -->
|
||
<view class="preferred-languages-modal" v-if="showPreferredModal" @click="hidePreferredLanguages">
|
||
<view class="preferred-content" @click.stop>
|
||
<view class="modal-header">
|
||
<text class="modal-title">{{ $t('mt.settings.contentLanguage') }}</text>
|
||
<view class="close-btn" @click="hidePreferredLanguages">
|
||
<text class="close-text">✕</text>
|
||
</view>
|
||
</view>
|
||
<view class="preferred-list">
|
||
<view
|
||
v-for="language in availableLanguages"
|
||
:key="`pref-${language.code}`"
|
||
class="preferred-item"
|
||
@click="togglePreferredLanguage(language.code)">
|
||
<view class="checkbox" :class="{ checked: isPreferredLanguage(language.code) }">
|
||
<text class="check-mark" v-if="isPreferredLanguage(language.code)">✓</text>
|
||
</view>
|
||
<text class="preferred-name">{{ language.name }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="modal-actions">
|
||
<view class="action-btn primary" @click="savePreferredLanguages">
|
||
<text class="action-text">{{ $t('mt.general.confirm') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 分类偏好弹窗 -->
|
||
<view class="category-modal" v-if="showCategoryModal" @click="hideCategoryPreferences">
|
||
<view class="category-content" @click.stop>
|
||
<view class="modal-header">
|
||
<text class="modal-title">{{ $t('mt.settings.categories') }}</text>
|
||
<view class="close-btn" @click="hideCategoryPreferences">
|
||
<text class="close-text">✕</text>
|
||
</view>
|
||
</view>
|
||
<view class="category-list">
|
||
<view
|
||
v-for="category in availableCategories"
|
||
:key="`cat-${category.id}`"
|
||
class="category-item"
|
||
@click="togglePreferredCategory(category.id)">
|
||
<view class="checkbox" :class="{ checked: isPreferredCategory(category.id) }">
|
||
<text class="check-mark" v-if="isPreferredCategory(category.id)">✓</text>
|
||
</view>
|
||
<text class="category-name">{{ category.name }}</text>
|
||
</view>
|
||
</view>
|
||
<view class="modal-actions">
|
||
<view class="action-btn primary" @click="savePreferredCategories">
|
||
<text class="action-text">{{ $t('mt.general.confirm') }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 阅读模式弹窗 -->
|
||
<view class="reading-modal" v-if="showReadingModal" @click="hideReadingMode">
|
||
<view class="reading-content" @click.stop>
|
||
<view class="modal-header">
|
||
<text class="modal-title">{{ $t('mt.settings.readingMode') }}</text>
|
||
<view class="close-btn" @click="hideReadingMode">
|
||
<text class="close-text">✕</text>
|
||
</view>
|
||
</view>
|
||
<view class="reading-list">
|
||
<view
|
||
v-for="mode in readingModes"
|
||
:key="mode.value"
|
||
class="reading-item"
|
||
:class="{ active: userPreferences.reading_mode === mode.value }"
|
||
@click="selectReadingMode(mode.value)">
|
||
<text class="reading-name">{{ mode.text }}</text>
|
||
<text class="reading-desc">{{ mode.desc }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 字体大小弹窗 -->
|
||
<view class="font-modal" v-if="showFontModal" @click="hideFontSize">
|
||
<view class="font-content" @click.stop>
|
||
<view class="modal-header">
|
||
<text class="modal-title">{{ $t('mt.settings.fontSize') }}</text>
|
||
<view class="close-btn" @click="hideFontSize">
|
||
<text class="close-text">✕</text>
|
||
</view>
|
||
</view>
|
||
<view class="font-list">
|
||
<view
|
||
v-for="size in fontSizes"
|
||
:key="size.value"
|
||
class="font-item"
|
||
:class="{ active: userPreferences.font_size === size.value }"
|
||
@click="selectFontSize(size.value)">
|
||
<text class="font-name" :style="{ fontSize: size.preview }">{{ size.text }}</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup lang="uts">
|
||
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
||
import type { UserPreferences } from './types.uts'
|
||
import supa from '@/components/supadb/aksupainstance.uts'
|
||
import { tt } from '@/utils/i18nfun.uts'
|
||
import i18n from '@/i18n/index.uts' // 保留用于语言切换
|
||
|
||
// 用户信息
|
||
const userName = ref<string>('用户')
|
||
const userEmail = ref<string>('user@example.com')
|
||
|
||
// 用户偏好设置
|
||
const userPreferences = ref<UserPreferences>({
|
||
preferred_languages: ['zh-CN'],
|
||
preferred_categories: ['news.technology', 'news.economy'],
|
||
reading_mode: 'light',
|
||
font_size: 'medium',
|
||
auto_translate: true,
|
||
notification_enabled: true
|
||
})
|
||
|
||
// 弹窗状态
|
||
const showLanguageModal = ref<boolean>(false)
|
||
const showPreferredModal = ref<boolean>(false)
|
||
const showCategoryModal = ref<boolean>(false)
|
||
const showReadingModal = ref<boolean>(false)
|
||
const showFontModal = ref<boolean>(false)
|
||
|
||
// 当前语言
|
||
const currentLanguageCode = ref<string>('zh-CN')
|
||
const currentLanguageName = ref<string>(tt('mt.language.zh-CN'))
|
||
|
||
// 临时偏好设置(用于弹窗中的选择)
|
||
const tempPreferredLanguages = ref<Array<string>>([])
|
||
const tempPreferredCategories = ref<Array<string>>([])
|
||
|
||
// 可选项数据
|
||
const availableLanguages = ref<Array<{code: string, name: string}>>([
|
||
{ code: 'zh-CN', name: tt('mt.language.zh-CN') },
|
||
{ code: 'en-US', name: tt('mt.language.en-US') },
|
||
{ code: 'ja-JP', name: tt('mt.language.ja-JP') },
|
||
{ code: 'ko-KR', name: tt('mt.language.ko-KR') },
|
||
{ code: 'fr-FR', name: tt('mt.language.fr-FR') },
|
||
{ code: 'de-DE', name: tt('mt.language.de-DE') },
|
||
{ code: 'es-ES', name: tt('mt.language.es-ES') },
|
||
{ code: 'ru-RU', name: tt('mt.language.ru-RU') }
|
||
])
|
||
|
||
const availableCategories = ref<Array<{id: string, name: string}>>([
|
||
{ id: 'news.politics', name: tt('mt.category.politics') },
|
||
{ id: 'news.economy', name: tt('mt.category.economy') },
|
||
{ id: 'news.technology', name: tt('mt.category.technology') },
|
||
{ id: 'news.sports', name: tt('mt.category.sports') },
|
||
{ id: 'news.entertainment', name: tt('mt.category.entertainment') },
|
||
{ id: 'news.health', name: tt('mt.category.health') },
|
||
{ id: 'news.education', name: tt('mt.category.education') },
|
||
{ id: 'news.international', name: tt('mt.category.international') }
|
||
])
|
||
|
||
const readingModes = ref<Array<{value: string, text: string, desc: string}>>([
|
||
{ value: 'light', text: tt('mt.settings.readingMode.light'), desc: tt('mt.settings.readingMode.lightDesc') },
|
||
{ value: 'dark', text: tt('mt.settings.readingMode.dark'), desc: tt('mt.settings.readingMode.darkDesc') },
|
||
{ value: 'auto', text: tt('mt.settings.readingMode.auto'), desc: tt('mt.settings.readingMode.autoDesc') }
|
||
])
|
||
|
||
const fontSizes = ref<Array<{value: string, text: string, preview: string}>>([
|
||
{ value: 'small', text: tt('mt.settings.fontSize.small'), preview: '14px' },
|
||
{ value: 'medium', text: tt('mt.settings.fontSize.medium'), preview: '16px' },
|
||
{ value: 'large', text: tt('mt.settings.fontSize.large'), preview: '18px' }
|
||
])
|
||
|
||
// 计算属性
|
||
const preferredLanguagesText = computed((): string => {
|
||
if (userPreferences.value.preferred_languages.length === 0) {
|
||
return tt('mt.settings.notSet')
|
||
}
|
||
|
||
const names: Array<string> = []
|
||
for (let i: Int = 0; i < userPreferences.value.preferred_languages.length; i++) {
|
||
const code = userPreferences.value.preferred_languages[i]
|
||
const language = availableLanguages.value.find(lang => lang.code === code)
|
||
if (language !== undefined) {
|
||
names.push(language.name)
|
||
}
|
||
}
|
||
|
||
return names.length > 0 ? names.join(', ') : tt('mt.settings.notSet')
|
||
})
|
||
|
||
const preferredCategoriesText = computed((): string => {
|
||
if (userPreferences.value.preferred_categories.length === 0) {
|
||
return tt('mt.settings.notSet')
|
||
}
|
||
|
||
const names: Array<string> = []
|
||
for (let i: Int = 0; i < userPreferences.value.preferred_categories.length; i++) {
|
||
const id = userPreferences.value.preferred_categories[i]
|
||
const category = availableCategories.value.find(cat => cat.id === id)
|
||
if (category !== undefined) {
|
||
names.push(category.name)
|
||
}
|
||
}
|
||
|
||
return names.length > 0 ? names.join(', ') : '未设置'
|
||
})
|
||
|
||
const readingModeText = computed((): string => {
|
||
const mode = readingModes.value.find(m => m.value === userPreferences.value.reading_mode)
|
||
return mode !== undefined ? mode.text : '浅色模式'
|
||
})
|
||
|
||
const fontSizeText = computed((): string => {
|
||
const size = fontSizes.value.find(s => s.value === userPreferences.value.font_size)
|
||
return size !== undefined ? size.text : '中'
|
||
})
|
||
|
||
// 语言设置相关函数
|
||
const showLanguageSelector = () => {
|
||
showLanguageModal.value = true
|
||
}
|
||
|
||
const hideLanguageSelector = () => {
|
||
showLanguageModal.value = false
|
||
}
|
||
|
||
const selectLanguage = (code: string) => {
|
||
currentLanguageCode.value = code
|
||
const language = availableLanguages.value.find(lang => lang.code === code)
|
||
if (language !== undefined) {
|
||
currentLanguageName.value = language.name
|
||
}
|
||
|
||
hideLanguageSelector()
|
||
saveUserPreferences()
|
||
|
||
uni.showToast({
|
||
title: '语言设置已保存',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 内容语言偏好相关函数
|
||
const showPreferredLanguages = () => {
|
||
tempPreferredLanguages.value = [...userPreferences.value.preferred_languages]
|
||
showPreferredModal.value = true
|
||
}
|
||
|
||
const hidePreferredLanguages = () => {
|
||
showPreferredModal.value = false
|
||
}
|
||
|
||
const isPreferredLanguage = (code: string): boolean => {
|
||
return tempPreferredLanguages.value.includes(code)
|
||
}
|
||
|
||
const togglePreferredLanguage = (code: string) => {
|
||
const index = tempPreferredLanguages.value.indexOf(code)
|
||
if (index >= 0) {
|
||
tempPreferredLanguages.value.splice(index, 1)
|
||
} else {
|
||
tempPreferredLanguages.value.push(code)
|
||
}
|
||
}
|
||
|
||
const savePreferredLanguages = () => {
|
||
userPreferences.value.preferred_languages = [...tempPreferredLanguages.value]
|
||
hidePreferredLanguages()
|
||
saveUserPreferences()
|
||
|
||
uni.showToast({
|
||
title: '语言偏好已保存',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 分类偏好相关函数
|
||
const showCategoryPreferences = () => {
|
||
tempPreferredCategories.value = [...userPreferences.value.preferred_categories]
|
||
showCategoryModal.value = true
|
||
}
|
||
|
||
const hideCategoryPreferences = () => {
|
||
showCategoryModal.value = false
|
||
}
|
||
|
||
const isPreferredCategory = (id: string): boolean => {
|
||
return tempPreferredCategories.value.includes(id)
|
||
}
|
||
|
||
const togglePreferredCategory = (id: string) => {
|
||
const index = tempPreferredCategories.value.indexOf(id)
|
||
if (index >= 0) {
|
||
tempPreferredCategories.value.splice(index, 1)
|
||
} else {
|
||
tempPreferredCategories.value.push(id)
|
||
}
|
||
}
|
||
|
||
const savePreferredCategories = () => {
|
||
userPreferences.value.preferred_categories = [...tempPreferredCategories.value]
|
||
hideCategoryPreferences()
|
||
saveUserPreferences()
|
||
|
||
uni.showToast({
|
||
title: '分类偏好已保存',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 阅读模式相关函数
|
||
const showReadingMode = () => {
|
||
showReadingModal.value = true
|
||
}
|
||
|
||
const hideReadingMode = () => {
|
||
showReadingModal.value = false
|
||
}
|
||
|
||
const selectReadingMode = (mode: string) => {
|
||
userPreferences.value.reading_mode = mode
|
||
hideReadingMode()
|
||
saveUserPreferences()
|
||
|
||
uni.showToast({
|
||
title: '阅读模式已更新',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 字体大小相关函数
|
||
const showFontSize = () => {
|
||
showFontModal.value = true
|
||
}
|
||
|
||
const hideFontSize = () => {
|
||
showFontModal.value = false
|
||
}
|
||
|
||
const selectFontSize = (size: string) => {
|
||
userPreferences.value.font_size = size
|
||
hideFontSize()
|
||
saveUserPreferences()
|
||
|
||
uni.showToast({
|
||
title: '字体大小已更新',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 开关设置函数
|
||
const toggleAutoTranslate = () => {
|
||
userPreferences.value.auto_translate = !userPreferences.value.auto_translate
|
||
saveUserPreferences()
|
||
|
||
const status = userPreferences.value.auto_translate ? '已开启' : '已关闭'
|
||
uni.showToast({
|
||
title: `自动翻译${status}`,
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
const toggleNotification = () => {
|
||
userPreferences.value.notification_enabled = !userPreferences.value.notification_enabled
|
||
saveUserPreferences()
|
||
|
||
const status = userPreferences.value.notification_enabled ? '已开启' : '已关闭'
|
||
uni.showToast({
|
||
title: `推送通知${status}`,
|
||
icon: 'success'
|
||
})
|
||
}
|
||
|
||
// 其他设置函数
|
||
const editProfile = () => {
|
||
uni.showToast({
|
||
title: '个人资料编辑功能开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
const clearChatHistory = () => {
|
||
uni.showModal({
|
||
title: '清空聊天记录',
|
||
content: '确定要删除所有AI聊天记录吗?此操作不可撤销。',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 这里调用清空聊天记录的API
|
||
uni.showToast({
|
||
title: '聊天记录已清空',
|
||
icon: 'success'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const showAISettings = () => {
|
||
uni.showToast({
|
||
title: 'AI设置功能开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
const exportData = () => {
|
||
uni.showModal({
|
||
title: '导出数据',
|
||
content: '将导出您的阅读记录、偏好设置等个人数据,是否继续?',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
// 这里调用数据导出的API
|
||
uni.showToast({
|
||
title: '数据导出功能开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const clearUserData = () => {
|
||
uni.showModal({
|
||
title: '清除用户数据',
|
||
content: '这将删除所有个人数据和记录,包括阅读历史、偏好设置等,此操作不可撤销!',
|
||
confirmColor: '#ef4444',
|
||
success: (res) => {
|
||
if (res.confirm) {
|
||
uni.showModal({
|
||
title: '最后确认',
|
||
content: '您确定要删除所有数据吗?',
|
||
confirmColor: '#ef4444',
|
||
success: (res2) => {
|
||
if (res2.confirm) {
|
||
// 这里调用清除数据的API
|
||
uni.showToast({
|
||
title: '数据清除功能开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
}
|
||
})
|
||
}
|
||
|
||
const showPrivacyPolicy = () => {
|
||
uni.showToast({
|
||
title: '隐私政策页面开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
const showTermsOfService = () => {
|
||
uni.showToast({
|
||
title: '使用条款页面开发中',
|
||
icon: 'none'
|
||
})
|
||
}
|
||
|
||
// 数据保存和加载
|
||
const saveUserPreferences = () => {
|
||
try {
|
||
uni.setStorageSync('user_preferences', userPreferences.value)
|
||
} catch (error) {
|
||
console.error('保存用户偏好失败:', error)
|
||
}
|
||
}
|
||
|
||
const loadUserPreferences = () => {
|
||
try {
|
||
const prefs = uni.getStorageSync('user_preferences')
|
||
if (prefs != null) {
|
||
userPreferences.value = prefs as UserPreferences
|
||
}
|
||
} catch (error) {
|
||
console.error('加载用户偏好失败:', error)
|
||
}
|
||
}
|
||
|
||
const loadUserInfo = () => {
|
||
// 这里应该从API或本地存储加载用户信息
|
||
try {
|
||
const userInfo = uni.getStorageSync('user_info')
|
||
if (userInfo != null) {
|
||
const info = userInfo as UTSJSONObject
|
||
const name = info.get('name')
|
||
const email = info.get('email')
|
||
if (name != null) userName.value = name as string
|
||
if (email != null) userEmail.value = email as string
|
||
}
|
||
} catch (error) {
|
||
console.error('加载用户信息失败:', error)
|
||
}
|
||
}
|
||
|
||
// 导航函数
|
||
const goBack = () => {
|
||
try {
|
||
uni.navigateBack({
|
||
delta: 1
|
||
})
|
||
} catch (error) {
|
||
console.error('返回异常:', error)
|
||
}
|
||
}
|
||
|
||
// 生命周期
|
||
onMounted(() => {
|
||
loadUserInfo()
|
||
loadUserPreferences()
|
||
})
|
||
|
||
onUnmounted(() => {
|
||
// 清理工作
|
||
})
|
||
</script>
|
||
|
||
<style>
|
||
.settings-page {
|
||
flex: 1;
|
||
background-color: #f5f5f5;
|
||
}
|
||
|
||
.settings-header {
|
||
background-color: #ffffff;
|
||
border-bottom: 1px solid #e5e5e5;
|
||
}
|
||
|
||
.header-content {
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 12px 16px;
|
||
}
|
||
|
||
.back-btn {
|
||
width: 40px;
|
||
height: 40px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border-radius: 20px;
|
||
background-color: #f3f4f6;
|
||
}
|
||
|
||
.back-icon {
|
||
font-size: 18px;
|
||
color: #374151;
|
||
}
|
||
|
||
.header-title {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.header-placeholder {
|
||
width: 40px;
|
||
}
|
||
|
||
.user-section {
|
||
margin: 12px;
|
||
}
|
||
|
||
.user-card {
|
||
flex-direction: row;
|
||
align-items: center;
|
||
padding: 20px;
|
||
background-color: #ffffff;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
.user-avatar {
|
||
width: 60px;
|
||
height: 60px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border-radius: 30px;
|
||
background-color: #3b82f6;
|
||
margin-right: 16px;
|
||
}
|
||
|
||
.avatar-text {
|
||
font-size: 24px;
|
||
color: #ffffff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.user-info {
|
||
flex: 1;
|
||
}
|
||
|
||
.user-name {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
color: #1f2937;
|
||
margin-bottom: 4px;
|
||
}
|
||
|
||
.user-email {
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
}
|
||
|
||
.edit-btn {
|
||
padding: 8px 16px;
|
||
background-color: #f3f4f6;
|
||
border-radius: 20px;
|
||
}
|
||
|
||
.edit-text {
|
||
font-size: 14px;
|
||
color: #374151;
|
||
}
|
||
|
||
.settings-section {
|
||
margin: 12px;
|
||
background-color: #ffffff;
|
||
border-radius: 12px;
|
||
}
|
||
|
||
.section-header {
|
||
padding: 16px 20px;
|
||
border-bottom: 1px solid #f3f4f6;
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 16px;
|
||
font-weight: bold;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.setting-item {
|
||
flex-direction: row;
|
||
align-items: center;
|
||
padding: 16px 20px;
|
||
border-bottom: 1px solid #f9fafb;
|
||
}
|
||
|
||
.setting-item:last-child {
|
||
border-bottom: none;
|
||
}
|
||
|
||
.item-content {
|
||
flex: 1;
|
||
}
|
||
|
||
.item-label {
|
||
font-size: 16px;
|
||
color: #1f2937;
|
||
margin-bottom: 2px;
|
||
}
|
||
|
||
.item-desc {
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
line-height: 20px;
|
||
}
|
||
|
||
.item-value {
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
}
|
||
|
||
.item-arrow {
|
||
font-size: 20px;
|
||
color: #d1d5db;
|
||
margin-left: 12px;
|
||
}
|
||
|
||
.toggle-switch {
|
||
width: 50px;
|
||
height: 30px;
|
||
border-radius: 15px;
|
||
background-color: #d1d5db;
|
||
justify-content: flex-start;
|
||
align-items: center;
|
||
padding: 2px;
|
||
margin-left: 12px;
|
||
}
|
||
|
||
.toggle-switch.active {
|
||
background-color: #3b82f6;
|
||
justify-content: flex-end;
|
||
}
|
||
|
||
.toggle-thumb {
|
||
width: 26px;
|
||
height: 26px;
|
||
border-radius: 13px;
|
||
background-color: #ffffff;
|
||
}
|
||
|
||
/* 弹窗通用样式 */
|
||
.language-modal, .preferred-languages-modal, .category-modal, .reading-modal, .font-modal {
|
||
position: fixed;
|
||
top: 0;
|
||
left: 0;
|
||
right: 0;
|
||
bottom: 0;
|
||
background-color: rgba(0, 0, 0, 0.5);
|
||
z-index: 1000;
|
||
justify-content: center;
|
||
align-items: center;
|
||
}
|
||
|
||
.language-content, .preferred-content, .category-content, .reading-content, .font-content {
|
||
width: 320px;
|
||
max-height: 500px;
|
||
background-color: #ffffff;
|
||
border-radius: 12px;
|
||
margin: 20px;
|
||
}
|
||
|
||
.modal-header {
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16px;
|
||
border-bottom: 1px solid #e5e5e5;
|
||
}
|
||
|
||
.modal-title {
|
||
font-size: 18px;
|
||
font-weight: bold;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.close-btn {
|
||
width: 32px;
|
||
height: 32px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border-radius: 16px;
|
||
background-color: #f3f4f6;
|
||
}
|
||
|
||
.close-text {
|
||
font-size: 16px;
|
||
color: #6b7280;
|
||
}
|
||
|
||
.language-list, .preferred-list, .category-list, .reading-list, .font-list {
|
||
max-height: 350px;
|
||
}
|
||
|
||
.language-item, .reading-item, .font-item {
|
||
flex-direction: row;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 16px;
|
||
border-bottom: 1px solid #f3f4f6;
|
||
}
|
||
|
||
.language-item.active, .reading-item.active, .font-item.active {
|
||
background-color: #eff6ff;
|
||
}
|
||
|
||
.language-name, .reading-name, .font-name {
|
||
font-size: 16px;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.language-item.active .language-name,
|
||
.reading-item.active .reading-name,
|
||
.font-item.active .font-name {
|
||
color: #3b82f6;
|
||
}
|
||
|
||
.language-code {
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
}
|
||
|
||
.reading-desc {
|
||
font-size: 14px;
|
||
color: #6b7280;
|
||
margin-top: 2px;
|
||
}
|
||
|
||
.preferred-item, .category-item {
|
||
flex-direction: row;
|
||
align-items: center;
|
||
padding: 16px;
|
||
border-bottom: 1px solid #f3f4f6;
|
||
}
|
||
|
||
.checkbox {
|
||
width: 24px;
|
||
height: 24px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border: 2px solid #d1d5db;
|
||
border-radius: 6px;
|
||
margin-right: 12px;
|
||
}
|
||
|
||
.checkbox.checked {
|
||
background-color: #3b82f6;
|
||
border-color: #3b82f6;
|
||
}
|
||
|
||
.check-mark {
|
||
font-size: 14px;
|
||
color: #ffffff;
|
||
font-weight: bold;
|
||
}
|
||
|
||
.preferred-name, .category-name {
|
||
font-size: 16px;
|
||
color: #1f2937;
|
||
}
|
||
|
||
.modal-actions {
|
||
padding: 16px;
|
||
border-top: 1px solid #e5e5e5;
|
||
}
|
||
|
||
.action-btn {
|
||
width: 100%;
|
||
height: 44px;
|
||
justify-content: center;
|
||
align-items: center;
|
||
border-radius: 8px;
|
||
}
|
||
|
||
.action-btn.primary {
|
||
background-color: #3b82f6;
|
||
}
|
||
|
||
.action-text {
|
||
font-size: 16px;
|
||
}
|
||
|
||
.action-btn.primary .action-text {
|
||
color: #ffffff;
|
||
}
|
||
</style>
|