765 lines
17 KiB
Vue
765 lines
17 KiB
Vue
<template>
|
|
<view class="privacy-container page-container-with-bg">
|
|
<!-- 隐私权限设置卡片 -->
|
|
<view class="privacy-settings-card">
|
|
<view class="card-header">
|
|
<text class="card-title">隐私权限</text>
|
|
</view>
|
|
<view class="settings-list">
|
|
<view class="setting-item">
|
|
<view class="setting-info">
|
|
<text class="setting-title">个人资料可见性</text>
|
|
<text class="setting-desc">控制其他用户查看您的个人信息</text>
|
|
</view>
|
|
<view class="setting-value" @click="showProfileVisibilityPicker">
|
|
<text class="value-text">{{ getVisibilityText(privacySettings.profileVisibility) }}</text>
|
|
<text class="value-arrow">→</text>
|
|
</view>
|
|
</view>
|
|
<view class="setting-item">
|
|
<view class="setting-info">
|
|
<text class="setting-title">宠物信息可见性</text>
|
|
<text class="setting-desc">控制其他用户查看您的宠物信息</text>
|
|
</view>
|
|
<view class="setting-value" @click="showPetVisibilityPicker">
|
|
<text class="value-text">{{ getVisibilityText(privacySettings.petVisibility) }}</text>
|
|
<text class="value-arrow">→</text>
|
|
</view>
|
|
</view>
|
|
<view class="setting-item">
|
|
<view class="setting-info">
|
|
<text class="setting-title">允许陌生人联系</text>
|
|
<text class="setting-desc">是否允许非好友用户向您发送消息</text>
|
|
</view>
|
|
<view class="setting-switch">
|
|
<u-switch
|
|
v-model="privacySettings.allowStrangerContact"
|
|
@change="onSettingChange('allowStrangerContact', $event)"
|
|
active-color="#FF8A80"
|
|
></u-switch>
|
|
</view>
|
|
</view>
|
|
<view class="setting-item">
|
|
<view class="setting-info">
|
|
<text class="setting-title">显示在线状态</text>
|
|
<text class="setting-desc">是否向其他用户显示您的在线状态</text>
|
|
</view>
|
|
<view class="setting-switch">
|
|
<u-switch
|
|
v-model="privacySettings.showOnlineStatus"
|
|
@change="onSettingChange('showOnlineStatus', $event)"
|
|
active-color="#FF8A80"
|
|
></u-switch>
|
|
</view>
|
|
</view>
|
|
<view class="setting-item">
|
|
<view class="setting-info">
|
|
<text class="setting-title">允许搜索</text>
|
|
<text class="setting-desc">是否允许其他用户通过搜索找到您</text>
|
|
</view>
|
|
<view class="setting-switch">
|
|
<u-switch
|
|
v-model="privacySettings.allowSearch"
|
|
@change="onSettingChange('allowSearch', $event)"
|
|
active-color="#FF8A80"
|
|
></u-switch>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 数据管理卡片 -->
|
|
<view class="data-management-card">
|
|
<view class="card-header">
|
|
<text class="card-title">数据管理</text>
|
|
</view>
|
|
<view class="data-list">
|
|
<view class="data-item" @click="exportData">
|
|
<view class="data-info">
|
|
<text class="data-title">导出我的数据</text>
|
|
<text class="data-desc">下载您在应用中的所有数据</text>
|
|
</view>
|
|
<view class="data-action">
|
|
<text class="action-icon">📥</text>
|
|
</view>
|
|
</view>
|
|
<view class="data-item" @click="viewDataUsage">
|
|
<view class="data-info">
|
|
<text class="data-title">数据使用情况</text>
|
|
<text class="data-desc">查看应用收集和使用的数据类型</text>
|
|
</view>
|
|
<view class="data-action">
|
|
<text class="action-icon">📊</text>
|
|
</view>
|
|
</view>
|
|
<view class="data-item" @click="clearCache">
|
|
<view class="data-info">
|
|
<text class="data-title">清理缓存数据</text>
|
|
<text class="data-desc">清除应用缓存以释放存储空间</text>
|
|
</view>
|
|
<view class="data-action">
|
|
<text class="action-icon">🗑️</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 账号安全卡片 -->
|
|
<view class="security-card">
|
|
<view class="card-header">
|
|
<text class="card-title">账号安全</text>
|
|
</view>
|
|
<view class="security-list">
|
|
<view class="security-item" @click="changePassword">
|
|
<view class="security-info">
|
|
<text class="security-title">修改密码</text>
|
|
<text class="security-desc">定期更换密码保护账号安全</text>
|
|
</view>
|
|
<view class="security-action">
|
|
<text class="action-arrow">→</text>
|
|
</view>
|
|
</view>
|
|
<view class="security-item" @click="viewLoginHistory">
|
|
<view class="security-info">
|
|
<text class="security-title">登录记录</text>
|
|
<text class="security-desc">查看最近的登录活动</text>
|
|
</view>
|
|
<view class="security-action">
|
|
<text class="action-arrow">→</text>
|
|
</view>
|
|
</view>
|
|
<view class="security-item">
|
|
<view class="security-info">
|
|
<text class="security-title">两步验证</text>
|
|
<text class="security-desc">开启两步验证增强账号安全</text>
|
|
</view>
|
|
<view class="security-switch">
|
|
<u-switch
|
|
v-model="privacySettings.twoFactorAuth"
|
|
@change="onTwoFactorChange"
|
|
active-color="#FF8A80"
|
|
></u-switch>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 危险操作卡片 -->
|
|
<view class="danger-card">
|
|
<view class="card-header">
|
|
<text class="card-title">危险操作</text>
|
|
</view>
|
|
<view class="danger-list">
|
|
<view class="danger-item" @click="deleteAllData">
|
|
<view class="danger-info">
|
|
<text class="danger-title">删除所有数据</text>
|
|
<text class="danger-desc">永久删除您的所有数据(不可恢复)</text>
|
|
</view>
|
|
<view class="danger-action">
|
|
<text class="action-arrow">→</text>
|
|
</view>
|
|
</view>
|
|
<view class="danger-item" @click="deleteAccount">
|
|
<view class="danger-info">
|
|
<text class="danger-title">注销账号</text>
|
|
<text class="danger-desc">永久删除账号和所有相关数据</text>
|
|
</view>
|
|
<view class="danger-action">
|
|
<text class="action-arrow">→</text>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
|
|
<!-- 选择器 -->
|
|
<u-picker
|
|
:show="showProfileVisibility"
|
|
:columns="visibilityColumns"
|
|
@confirm="onProfileVisibilityConfirm"
|
|
@cancel="showProfileVisibility = false"
|
|
></u-picker>
|
|
|
|
<u-picker
|
|
:show="showPetVisibility"
|
|
:columns="visibilityColumns"
|
|
@confirm="onPetVisibilityConfirm"
|
|
@cancel="showPetVisibility = false"
|
|
></u-picker>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
import { reactive, ref, onMounted } from 'vue'
|
|
|
|
export default {
|
|
name: 'PrivacyPage',
|
|
setup() {
|
|
// 响应式数据
|
|
const privacySettings = reactive({
|
|
profileVisibility: 'friends',
|
|
petVisibility: 'public',
|
|
allowStrangerContact: false,
|
|
showOnlineStatus: true,
|
|
allowSearch: true,
|
|
twoFactorAuth: false
|
|
})
|
|
|
|
const showProfileVisibility = ref(false)
|
|
const showPetVisibility = ref(false)
|
|
|
|
const visibilityColumns = ref([
|
|
[
|
|
{ text: '公开', value: 'public' },
|
|
{ text: '仅好友', value: 'friends' },
|
|
{ text: '仅自己', value: 'private' }
|
|
]
|
|
])
|
|
|
|
// 生命周期
|
|
onMounted(() => {
|
|
loadSettings()
|
|
})
|
|
|
|
// 方法定义
|
|
const loadSettings = () => {
|
|
try {
|
|
const savedSettings = uni.getStorageSync('privacySettings')
|
|
if (savedSettings) {
|
|
Object.assign(privacySettings, savedSettings)
|
|
}
|
|
} catch (error) {
|
|
console.error('加载隐私设置失败:', error)
|
|
}
|
|
}
|
|
|
|
const saveSettings = () => {
|
|
uni.setStorageSync('privacySettings', privacySettings)
|
|
}
|
|
|
|
const getVisibilityText = (value) => {
|
|
const textMap = {
|
|
'public': '公开',
|
|
'friends': '仅好友',
|
|
'private': '仅自己'
|
|
}
|
|
return textMap[value] || '公开'
|
|
}
|
|
|
|
const onSettingChange = (key, value) => {
|
|
privacySettings[key] = value
|
|
saveSettings()
|
|
|
|
uni.showToast({
|
|
title: value ? '已开启' : '已关闭',
|
|
icon: 'success'
|
|
})
|
|
}
|
|
|
|
const onTwoFactorChange = (value) => {
|
|
if (value) {
|
|
uni.showModal({
|
|
title: '开启两步验证',
|
|
content: '开启两步验证后,登录时需要额外的验证码。确定要开启吗?',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
privacySettings.twoFactorAuth = true
|
|
saveSettings()
|
|
uni.showToast({
|
|
title: '两步验证已开启',
|
|
icon: 'success'
|
|
})
|
|
} else {
|
|
privacySettings.twoFactorAuth = false
|
|
}
|
|
}
|
|
})
|
|
} else {
|
|
privacySettings.twoFactorAuth = false
|
|
saveSettings()
|
|
uni.showToast({
|
|
title: '两步验证已关闭',
|
|
icon: 'success'
|
|
})
|
|
}
|
|
}
|
|
|
|
const showProfileVisibilityPicker = () => {
|
|
showProfileVisibility.value = true
|
|
}
|
|
|
|
const showPetVisibilityPicker = () => {
|
|
showPetVisibility.value = true
|
|
}
|
|
|
|
const onProfileVisibilityConfirm = (e) => {
|
|
privacySettings.profileVisibility = e.value[0].value
|
|
saveSettings()
|
|
showProfileVisibility.value = false
|
|
|
|
uni.showToast({
|
|
title: '设置已保存',
|
|
icon: 'success'
|
|
})
|
|
}
|
|
|
|
const onPetVisibilityConfirm = (e) => {
|
|
privacySettings.petVisibility = e.value[0].value
|
|
saveSettings()
|
|
showPetVisibility.value = false
|
|
|
|
uni.showToast({
|
|
title: '设置已保存',
|
|
icon: 'success'
|
|
})
|
|
}
|
|
|
|
const exportData = () => {
|
|
uni.showLoading({
|
|
title: '正在导出数据...'
|
|
})
|
|
|
|
setTimeout(() => {
|
|
uni.hideLoading()
|
|
uni.showModal({
|
|
title: '数据导出',
|
|
content: '您的数据已导出完成,将通过邮件发送给您。',
|
|
showCancel: false
|
|
})
|
|
}, 2000)
|
|
}
|
|
|
|
const viewDataUsage = () => {
|
|
const dataTypes = [
|
|
'• 个人基本信息(昵称、头像等)',
|
|
'• 宠物信息和照片',
|
|
'• 使用行为数据',
|
|
'• 设备信息',
|
|
'• 位置信息(仅在使用相关功能时)'
|
|
]
|
|
|
|
uni.showModal({
|
|
title: '数据使用情况',
|
|
content: `我们收集以下类型的数据:\n\n${dataTypes.join('\n')}`,
|
|
showCancel: false
|
|
})
|
|
}
|
|
|
|
const clearCache = () => {
|
|
uni.showModal({
|
|
title: '清理缓存',
|
|
content: '确定要清理应用缓存吗?这将删除临时文件和图片缓存。',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.showLoading({
|
|
title: '正在清理...'
|
|
})
|
|
|
|
setTimeout(() => {
|
|
uni.hideLoading()
|
|
uni.showToast({
|
|
title: '缓存清理完成',
|
|
icon: 'success'
|
|
})
|
|
}, 1500)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
const changePassword = () => {
|
|
uni.showToast({
|
|
title: '功能开发中',
|
|
icon: 'none'
|
|
})
|
|
}
|
|
|
|
const viewLoginHistory = () => {
|
|
const loginHistory = [
|
|
'今天 14:30 - iPhone (当前设备)',
|
|
'昨天 09:15 - iPhone',
|
|
'3天前 20:45 - iPhone',
|
|
'1周前 16:20 - iPhone'
|
|
]
|
|
|
|
uni.showModal({
|
|
title: '登录记录',
|
|
content: `最近登录记录:\n\n${loginHistory.join('\n')}`,
|
|
showCancel: false
|
|
})
|
|
}
|
|
|
|
const deleteAllData = () => {
|
|
uni.showModal({
|
|
title: '删除所有数据',
|
|
content: '此操作将永久删除您的所有数据,包括宠物信息、记录等,且无法恢复。确定要继续吗?',
|
|
confirmColor: '#FF5722',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.showModal({
|
|
title: '最终确认',
|
|
content: '请再次确认:您真的要删除所有数据吗?此操作不可撤销!',
|
|
confirmColor: '#FF5722',
|
|
success: (res2) => {
|
|
if (res2.confirm) {
|
|
// 清除所有本地数据
|
|
uni.clearStorageSync()
|
|
|
|
uni.showToast({
|
|
title: '数据已删除',
|
|
icon: 'success'
|
|
})
|
|
|
|
setTimeout(() => {
|
|
uni.reLaunch({
|
|
url: '/pages/pets/pets'
|
|
})
|
|
}, 1500)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
const deleteAccount = () => {
|
|
uni.showModal({
|
|
title: '注销账号',
|
|
content: '注销账号将永久删除您的账号和所有相关数据,此操作不可恢复。确定要继续吗?',
|
|
confirmColor: '#FF5722',
|
|
success: (res) => {
|
|
if (res.confirm) {
|
|
uni.showModal({
|
|
title: '最终确认',
|
|
content: '请再次确认:您真的要注销账号吗?注销后将无法找回!',
|
|
confirmColor: '#FF5722',
|
|
success: (res2) => {
|
|
if (res2.confirm) {
|
|
uni.showLoading({
|
|
title: '正在注销...'
|
|
})
|
|
|
|
setTimeout(() => {
|
|
uni.hideLoading()
|
|
uni.clearStorageSync()
|
|
|
|
uni.showToast({
|
|
title: '账号已注销',
|
|
icon: 'success'
|
|
})
|
|
|
|
setTimeout(() => {
|
|
uni.reLaunch({
|
|
url: '/pages/pets/pets'
|
|
})
|
|
}, 1500)
|
|
}, 2000)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
return {
|
|
privacySettings,
|
|
showProfileVisibility,
|
|
showPetVisibility,
|
|
visibilityColumns,
|
|
getVisibilityText,
|
|
onSettingChange,
|
|
onTwoFactorChange,
|
|
showProfileVisibilityPicker,
|
|
showPetVisibilityPicker,
|
|
onProfileVisibilityConfirm,
|
|
onPetVisibilityConfirm,
|
|
exportData,
|
|
viewDataUsage,
|
|
clearCache,
|
|
changePassword,
|
|
viewLoginHistory,
|
|
deleteAllData,
|
|
deleteAccount
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.privacy-container {
|
|
background: linear-gradient(135deg, #FF8A80 0%, #FFB6C1 25%, #FECFEF 50%, #F8BBD9 100%);
|
|
min-height: 100vh;
|
|
padding-bottom: 40rpx;
|
|
}
|
|
|
|
/* 通用卡片样式 */
|
|
.privacy-settings-card,
|
|
.data-management-card,
|
|
.security-card,
|
|
.danger-card {
|
|
background: rgba(255, 255, 255, 0.95);
|
|
backdrop-filter: blur(20rpx);
|
|
margin: 0 30rpx 24rpx 30rpx;
|
|
border-radius: 24rpx;
|
|
padding: 32rpx;
|
|
box-shadow: 0 8rpx 32rpx rgba(255, 138, 128, 0.2);
|
|
border: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
.card-header {
|
|
margin-bottom: 24rpx;
|
|
|
|
.card-title {
|
|
font-size: 32rpx;
|
|
font-weight: 600;
|
|
color: #333333;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 设置列表 */
|
|
.settings-list {
|
|
.setting-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 24rpx 0;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
.setting-info {
|
|
flex: 1;
|
|
|
|
.setting-title {
|
|
display: block;
|
|
font-size: 30rpx;
|
|
font-weight: 500;
|
|
color: #333333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.setting-desc {
|
|
font-size: 24rpx;
|
|
color: #666666;
|
|
line-height: 1.4;
|
|
}
|
|
}
|
|
|
|
.setting-value {
|
|
display: flex;
|
|
align-items: center;
|
|
margin-left: 24rpx;
|
|
transition: all 0.3s ease;
|
|
|
|
&:active {
|
|
transform: scale(0.95);
|
|
}
|
|
|
|
.value-text {
|
|
font-size: 26rpx;
|
|
color: #FF8A80;
|
|
margin-right: 8rpx;
|
|
}
|
|
|
|
.value-arrow {
|
|
font-size: 24rpx;
|
|
color: #FF8A80;
|
|
}
|
|
}
|
|
|
|
.setting-switch {
|
|
margin-left: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 数据管理列表 */
|
|
.data-list {
|
|
.data-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 24rpx 0;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
transition: all 0.3s ease;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&:active {
|
|
background: rgba(255, 138, 128, 0.05);
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.data-info {
|
|
flex: 1;
|
|
|
|
.data-title {
|
|
display: block;
|
|
font-size: 30rpx;
|
|
font-weight: 500;
|
|
color: #333333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.data-desc {
|
|
font-size: 24rpx;
|
|
color: #666666;
|
|
}
|
|
}
|
|
|
|
.data-action {
|
|
margin-left: 24rpx;
|
|
|
|
.action-icon {
|
|
font-size: 32rpx;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 安全设置列表 */
|
|
.security-list {
|
|
.security-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 24rpx 0;
|
|
border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
|
|
transition: all 0.3s ease;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&:active {
|
|
background: rgba(255, 138, 128, 0.05);
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.security-info {
|
|
flex: 1;
|
|
|
|
.security-title {
|
|
display: block;
|
|
font-size: 30rpx;
|
|
font-weight: 500;
|
|
color: #333333;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.security-desc {
|
|
font-size: 24rpx;
|
|
color: #666666;
|
|
}
|
|
}
|
|
|
|
.security-action {
|
|
margin-left: 24rpx;
|
|
|
|
.action-arrow {
|
|
font-size: 24rpx;
|
|
color: #FF8A80;
|
|
}
|
|
}
|
|
|
|
.security-switch {
|
|
margin-left: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 危险操作卡片 */
|
|
.danger-card {
|
|
border: 2rpx solid rgba(255, 87, 34, 0.2);
|
|
|
|
.card-title {
|
|
color: #FF5722;
|
|
}
|
|
}
|
|
|
|
.danger-list {
|
|
.danger-item {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
padding: 24rpx 0;
|
|
border-bottom: 1rpx solid rgba(255, 87, 34, 0.1);
|
|
transition: all 0.3s ease;
|
|
|
|
&:last-child {
|
|
border-bottom: none;
|
|
}
|
|
|
|
&:active {
|
|
background: rgba(255, 87, 34, 0.05);
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.danger-info {
|
|
flex: 1;
|
|
|
|
.danger-title {
|
|
display: block;
|
|
font-size: 30rpx;
|
|
font-weight: 500;
|
|
color: #FF5722;
|
|
margin-bottom: 8rpx;
|
|
}
|
|
|
|
.danger-desc {
|
|
font-size: 24rpx;
|
|
color: #FF8A65;
|
|
}
|
|
}
|
|
|
|
.danger-action {
|
|
margin-left: 24rpx;
|
|
|
|
.action-arrow {
|
|
font-size: 24rpx;
|
|
color: #FF5722;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 响应式设计 */
|
|
@media (max-width: 375px) {
|
|
.privacy-container {
|
|
.privacy-settings-card,
|
|
.data-management-card,
|
|
.security-card,
|
|
.danger-card {
|
|
margin: 0 20rpx 20rpx 20rpx;
|
|
padding: 24rpx;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* 动画效果 */
|
|
@keyframes fadeIn {
|
|
from {
|
|
opacity: 0;
|
|
transform: translateY(20rpx);
|
|
}
|
|
to {
|
|
opacity: 1;
|
|
transform: translateY(0);
|
|
}
|
|
}
|
|
|
|
.privacy-container > view {
|
|
animation: fadeIn 0.5s ease-out;
|
|
}
|
|
|
|
.privacy-container > view:nth-child(1) { animation-delay: 0.1s; }
|
|
.privacy-container > view:nth-child(2) { animation-delay: 0.2s; }
|
|
.privacy-container > view:nth-child(3) { animation-delay: 0.3s; }
|
|
.privacy-container > view:nth-child(4) { animation-delay: 0.4s; }
|
|
</style>
|