Files
taimed-international-app/pages/user/settings/index.vue

443 lines
8.9 KiB
Vue

<template>
<view class="settings-page">
<!-- 自定义导航栏 -->
<nav-bar :title="$t('user.settings')"></nav-bar>
<view class="settings-content">
<!-- 设置列表 -->
<view class="settings-list">
<view
v-for="item in settingItems"
:key="item.id"
class="setting-item"
@click="handleSettingClick(item)"
>
<text class="label">{{ item.label }}</text>
<view class="value-wrapper">
<text class="value">{{ item.value }}</text>
<wd-icon name="arrow-right" size="16px" color="#aaa" />
</view>
</view>
</view>
<!-- 操作按钮 -->
<view class="action-buttons">
<wd-button type="info" block :round="false" custom-class="logout-btn" @click="handleLogoff">{{ $t('user.logoff') }}</wd-button>
<wd-button type="error" block :round="false" @click="handleLogout">
{{ $t('user.logout') }}
</wd-button>
</view>
</view>
<!-- 微信二维码弹窗 -->
<wd-popup v-model="showQrCode" position="bottom" :closeable="true">
<view class="qrcode-modal">
<text class="modal-title">{{ $t('user.wechatTip') }}</text>
<image
src="/static/qiyeWx.jpg"
mode="aspectFit"
class="qrcode-image"
@click="previewQrCode"
/>
</view>
</wd-popup>
<!-- 语言选择弹窗 -->
<wd-popup v-model="showLanguageSelect" position="bottom" :closeable="true">
<view class="language-modal">
<text class="modal-title">{{ $t('user.languageSelect') }}</text>
<view class="language-list">
<view
v-for="lang in availableLanguages"
:key="lang.code"
class="language-item"
:class="{ active: (userStore.language || uni.getLocale()) === lang.code }"
@click="selectLanguage(lang.code)"
>
<text class="language-name">{{ lang.name }}</text>
<wd-icon v-if="(userStore.language || uni.getLocale()) === lang.code" name="check" size="20px" color="#54a966" />
</view>
</view>
</view>
</wd-popup>
<wd-message-box />
</view>
</template>
<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { useSysStore } from '@/stores/sys'
import { useUserStore } from '@/stores/user'
import { useI18n } from 'vue-i18n'
import { useMessage } from '@/uni_modules/wot-design-uni'
import { makePhoneCall, copyToClipboard } from '@/utils/index'
const { t, locale } = useI18n()
const sysStore = useSysStore()
const userStore = useUserStore()
const message = useMessage()
// 导航栏高度
const statusBarHeight = ref(0)
const navbarHeight = ref('44px')
// 弹窗状态
const showQrCode = ref(false)
const showLanguageSelect = ref(false)
// 可选语言列表
const availableLanguages = computed(() => [
{ code: 'en', name: t('locale.en') },
{ code: 'zh-Hans', name: t('locale.zh-hans') }
])
// 获取当前语言名称
const getCurrentLanguageName = () => {
const currentLang = userStore.language || uni.getLocale()
const language = availableLanguages.value.find(lang => lang.code === currentLang)
return language ? language.name : currentLang
}
// 设置项列表
const settingItems = computed(() => [
{
id: 0,
label: t('user.language'),
value: getCurrentLanguageName(),
type: 'language'
},
{
id: 1,
label: t('user.hotline'),
value: '022-24142321',
type: 'tel'
},
{
id: 2,
label: t('user.customerEmail'),
value: 'appyilujiankang@sina.com',
type: 'email'
},
{
id: 3,
label: t('user.wechat'),
value: '',
type: 'wechat'
},
{
id: 4,
label: t('user.checkVersion'),
value: '',
type: 'version'
}
])
/**
* 获取导航栏高度
*/
const getNavbarHeight = () => {
const systemInfo = uni.getSystemInfoSync()
statusBarHeight.value = systemInfo.statusBarHeight || 0
let navBarHeight = 44
if (systemInfo.model.indexOf('iPhone') !== -1 && parseInt(systemInfo.model.slice(-2)) >= 11) {
navBarHeight = 48
}
const totalHeight = statusBarHeight.value + navBarHeight
navbarHeight.value = totalHeight + 'px'
}
/**
* 处理设置项点击
*/
const handleSettingClick = (item: any) => {
switch (item.type) {
case 'language':
showLanguageSelect.value = true
break
case 'tel':
handlePhoneCall(item.value, item.label)
break
case 'email':
handleCopyEmail(item.value, item.label)
break
case 'wechat':
showQrCode.value = true
break
case 'version':
checkVersion()
break
}
}
/**
* 拨打电话
*/
const handlePhoneCall = (phoneNumber: string, title: string) => {
makePhoneCall(phoneNumber, title, t)
}
/**
* 复制到剪贴板
*/
const handleCopyEmail = (content: string, title: string) => {
copyToClipboard(content, title, t)
}
/**
* 预览二维码
*/
const previewQrCode = () => {
showQrCode.value = false
uni.previewImage({
urls: ['/static/qiyeWx.jpg']
})
}
/**
* 选择语言
*/
const selectLanguage = (languageCode: string) => {
try {
uni.setLocale(languageCode)
// 保存语言设置到用户存储
sysStore.setLanguage(languageCode)
// 更新i18n语言
locale.value = languageCode
} catch (error) {
console.error('语言切换失败:', error)
uni.showToast({
title: t('user.languageChangeFailed'),
icon: 'none'
})
}
}
/**
* 检查版本更新
*/
const checkVersion = () => {
// #ifdef APP-PLUS
// TODO: 集成 uni-upgrade-center-app 插件
uni.showToast({
title: '当前已是最新版本',
icon: 'none'
})
// #endif
// #ifndef APP-PLUS
uni.showToast({
title: '仅支持APP端检查更新',
icon: 'none'
})
// #endif
}
/**
* 注销账户
*/
const handleLogoff = () => {
message.confirm({
title: t('global.tips'),
msg: t('user.logoffConfirm'),
}).then(() => {
message.confirm({
title: t('global.tips'),
msg: t('user.logoffConfirmAgain'),
}).then(() => {
performLogout()
}).catch(() => {
// 取消注销账户
})
}).catch(() => {
// 取消注销账户
})
}
/**
* 退出登录
*/
const handleLogout = () => {
message.confirm({
title: t('global.tips'),
msg: t('user.logoutConfirm'),
}).then(() => {
performLogout()
}).catch(() => {
// 取消退出登录
})
}
/**
* 执行退出登录
*/
const performLogout = () => {
// 清除用户信息
userStore.logout()
uni.reLaunch({
url: '/pages/login/login'
})
}
onMounted(() => {
getNavbarHeight()
})
</script>
<style lang="scss" scoped>
$theme-color: #54a966;
.settings-page {
min-height: 100vh;
background-color: #f7faf9;
}
.custom-navbar {
position: fixed;
top: 0;
left: 0;
right: 0;
z-index: 999;
background-color: #fff;
border-bottom: 1rpx solid #e5e5e5;
.navbar-content {
display: flex;
align-items: center;
justify-content: center;
height: 44px;
position: relative;
.navbar-left {
position: absolute;
left: 10px;
display: flex;
align-items: center;
padding: 10rpx;
}
.navbar-title {
font-size: 16px;
font-weight: 700;
color: #333;
}
}
}
.settings-content {
padding: 20rpx;
}
.settings-list {
background: #fff;
border-radius: 15rpx;
overflow: hidden;
margin-bottom: 40rpx;
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
}
.setting-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx;
border-bottom: 1rpx solid #e0e0e0;
&:last-child {
border-bottom: none;
}
&:active {
background-color: #f5f5f5;
}
.label {
font-size: 30rpx;
color: #333;
width: 40%;
}
.value-wrapper {
flex: 1;
display: flex;
align-items: center;
justify-content: flex-end;
.value {
font-size: 28rpx;
color: #b0b0b0;
margin-right: 10rpx;
}
}
}
.action-buttons {
padding: 40rpx 30rpx 60rpx;
:deep(.logout-btn) {
margin-bottom: 40rpx;
background-color: #e5e5e5;
color: #8a1a1a;
}
}
.qrcode-modal {
padding: 40rpx;
text-align: center;
.modal-title {
display: block;
font-size: 28rpx;
color: #999;
margin-bottom: 30rpx;
}
.qrcode-image {
width: 400rpx;
height: 400rpx;
margin: 0 auto;
}
}
.language-modal {
padding: 40rpx;
.modal-title {
display: block;
font-size: 32rpx;
font-weight: bold;
color: #333;
margin-bottom: 30rpx;
text-align: center;
}
.language-list {
.language-item {
display: flex;
align-items: center;
justify-content: space-between;
padding: 30rpx 20rpx;
border-bottom: 1rpx solid #f0f0f0;
&.active {
background-color: #f7faf9;
}
&:last-child {
border-bottom: none;
}
.language-name {
font-size: 30rpx;
color: #333;
}
}
}
}
</style>