UI优化
This commit is contained in:
14
components.d.ts
vendored
14
components.d.ts
vendored
@@ -33,19 +33,5 @@ declare module 'vue' {
|
||||
UserMomentsModal: typeof import('./src/components/moment/UserMomentsModal.vue')['default']
|
||||
VideoPlayer: typeof import('./src/components/common/VideoPlayer.vue')['default']
|
||||
VisibilitySelector: typeof import('./src/components/moment/VisibilitySelector.vue')['default']
|
||||
WdActionSheet: typeof import('wot-design-uni/components/wd-action-sheet/wd-action-sheet.vue')['default']
|
||||
WdBadge: typeof import('wot-design-uni/components/wd-badge/wd-badge.vue')['default']
|
||||
WdButton: typeof import('wot-design-uni/components/wd-button/wd-button.vue')['default']
|
||||
WdCell: typeof import('wot-design-uni/components/wd-cell/wd-cell.vue')['default']
|
||||
WdEmpty: typeof import('wot-design-uni/components/wd-empty/wd-empty.vue')['default']
|
||||
WdIcon: typeof import('wot-design-uni/components/wd-icon/wd-icon.vue')['default']
|
||||
WdImg: typeof import('wot-design-uni/components/wd-img/wd-img.vue')['default']
|
||||
WdLoading: typeof import('wot-design-uni/components/wd-loading/wd-loading.vue')['default']
|
||||
WdMessageBox: typeof import('wot-design-uni/components/wd-message-box/wd-message-box.vue')['default']
|
||||
WdPopup: typeof import('wot-design-uni/components/wd-popup/wd-popup.vue')['default']
|
||||
WdSearch: typeof import('wot-design-uni/components/wd-search/wd-search.vue')['default']
|
||||
WdSwipeAction: typeof import('wot-design-uni/components/wd-swipe-action/wd-swipe-action.vue')['default']
|
||||
WdSwitch: typeof import('wot-design-uni/components/wd-switch/wd-switch.vue')['default']
|
||||
WdToast: typeof import('wot-design-uni/components/wd-toast/wd-toast.vue')['default']
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,76 +1,112 @@
|
||||
<template>
|
||||
<wd-navbar
|
||||
:title="title"
|
||||
:left-arrow="leftArrow"
|
||||
:fixed="fixed"
|
||||
:placeholder="placeholder"
|
||||
:bordered="bordered"
|
||||
:safe-area-inset-top="safeAreaInsetTop"
|
||||
:z-index="zIndex"
|
||||
custom-class="app-navbar"
|
||||
@click-left="onClickLeft"
|
||||
@click-right="onClickRight"
|
||||
>
|
||||
<template v-if="$slots.left" #left>
|
||||
<slot name="left" />
|
||||
</template>
|
||||
<template v-if="$slots.title" #title>
|
||||
<slot name="title" />
|
||||
</template>
|
||||
<template v-if="$slots.right" #right>
|
||||
<slot name="right" />
|
||||
</template>
|
||||
</wd-navbar>
|
||||
<view :class="{ dark: isDark }">
|
||||
<wd-navbar
|
||||
:title="title"
|
||||
:left-text="leftText"
|
||||
:right-text="rightText"
|
||||
:left-arrow="leftArrow"
|
||||
:fixed="fixed"
|
||||
:placeholder="placeholder"
|
||||
:safe-area-inset-top="safeAreaInsetTop"
|
||||
:bordered="bordered"
|
||||
custom-class="app-nav-bar"
|
||||
@click-left="handleClickLeft"
|
||||
@click-right="handleClickRight"
|
||||
>
|
||||
<!-- 插槽透传 -->
|
||||
<template #left v-if="$slots.left">
|
||||
<slot name="left" />
|
||||
</template>
|
||||
<template #title v-if="$slots.title">
|
||||
<slot name="title" />
|
||||
</template>
|
||||
<template #right v-if="$slots.right">
|
||||
<slot name="right" />
|
||||
</template>
|
||||
</wd-navbar>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useTheme } from '@/composables/useTheme'
|
||||
|
||||
const { isDark } = useTheme()
|
||||
|
||||
interface Props {
|
||||
title?: string
|
||||
leftText?: string
|
||||
rightText?: string
|
||||
leftArrow?: boolean
|
||||
fixed?: boolean
|
||||
placeholder?: boolean
|
||||
bordered?: boolean
|
||||
safeAreaInsetTop?: boolean
|
||||
zIndex?: number
|
||||
bordered?: boolean
|
||||
// 自定义点击左侧逻辑,如果不传则默认返回上一页
|
||||
customBack?: boolean
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
title: '',
|
||||
leftText: '',
|
||||
rightText: '',
|
||||
leftArrow: true,
|
||||
fixed: true,
|
||||
placeholder: true,
|
||||
bordered: true,
|
||||
safeAreaInsetTop: true,
|
||||
zIndex: 100
|
||||
bordered: false,
|
||||
customBack: false
|
||||
})
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'click-left'): void
|
||||
(e: 'click-right'): void
|
||||
}>()
|
||||
const emit = defineEmits(['click-left', 'click-right'])
|
||||
|
||||
function onClickLeft() {
|
||||
emit('click-left')
|
||||
// 默认返回上一页
|
||||
if (props.leftArrow) {
|
||||
uni.navigateBack({
|
||||
fail: () => {
|
||||
// 如果没有上一页,则跳转到首页
|
||||
uni.reLaunch({ url: '/pages/index/index' })
|
||||
}
|
||||
})
|
||||
function handleClickLeft() {
|
||||
if (props.customBack) {
|
||||
emit('click-left')
|
||||
} else {
|
||||
// 默认行为:返回上一页,如果无法返回则去首页
|
||||
const pages = getCurrentPages()
|
||||
if (pages.length > 1) {
|
||||
uni.navigateBack()
|
||||
} else {
|
||||
uni.reLaunch({ url: '/pages/index/index' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function onClickRight() {
|
||||
function handleClickRight() {
|
||||
emit('click-right')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.app-navbar {
|
||||
--wot-navbar-bg-color: var(--nav-bg, #ededed);
|
||||
--wot-navbar-title-color: var(--text-primary, #333);
|
||||
--wot-navbar-icon-color: var(--text-primary, #333);
|
||||
<style lang="scss" scoped>
|
||||
:deep(.app-nav-bar) {
|
||||
// 适配暗黑模式的背景色和文字颜色
|
||||
// 假设 src/uni.scss 或 variables.scss 中定义了这些 CSS 变量
|
||||
background-color: var(--bg-content) !important;
|
||||
|
||||
.wd-navbar__title {
|
||||
color: var(--text-primary) !important;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wd-navbar__text {
|
||||
color: var(--color-primary) !important;
|
||||
}
|
||||
|
||||
.wd-icon {
|
||||
color: var(--text-primary) !important;
|
||||
}
|
||||
}
|
||||
|
||||
// 暗黑模式下的特殊覆盖(如果 CSS 变量不够用)
|
||||
.dark {
|
||||
:deep(.app-nav-bar) {
|
||||
background-color: #1c1c1e !important; // 兜底暗色
|
||||
|
||||
.wd-navbar__title {
|
||||
color: #ffffff !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -156,3 +156,107 @@ function switchTab(name: string) {
|
||||
line-height: 1;
|
||||
}
|
||||
</style>
|
||||
<!--/*-->
|
||||
<!--<template>-->
|
||||
<!-- <view :class="{ dark: isDark }">-->
|
||||
<!-- <wd-tabbar-->
|
||||
<!-- :modelValue="current"-->
|
||||
<!-- fixed-->
|
||||
<!-- placeholder-->
|
||||
<!-- safe-area-inset-bottom-->
|
||||
<!-- bordered-->
|
||||
<!-- custom-class="app-tab-bar"-->
|
||||
<!-- @change="handleChange"-->
|
||||
<!-- >-->
|
||||
<!-- <wd-tabbar-item-->
|
||||
<!-- v-for="(item, index) in list"-->
|
||||
<!-- :key="index"-->
|
||||
<!-- :name="item.pagePath"-->
|
||||
<!-- :title="item.text"-->
|
||||
<!-- :value="item.badge > 0 ? item.badge : null"-->
|
||||
<!-- :icon="item.icon"-->
|
||||
<!-- >-->
|
||||
<!-- </wd-tabbar-item>-->
|
||||
<!-- </wd-tabbar>-->
|
||||
<!-- </view>-->
|
||||
<!--</template>-->
|
||||
|
||||
<!--<script setup lang="ts">-->
|
||||
<!--import { computed } from 'vue'-->
|
||||
<!--import { useTheme } from '@/composables/useTheme'-->
|
||||
<!--// 保持原有的 store 引用-->
|
||||
<!--import { useAppStore } from '@/stores'-->
|
||||
|
||||
<!--const props = defineProps<{-->
|
||||
<!-- active?: string-->
|
||||
<!--}>()-->
|
||||
|
||||
<!--const { isDark } = useTheme()-->
|
||||
<!--const appStore = useAppStore()-->
|
||||
|
||||
<!--// 核心修改:移除 image 路径,改用 Wot-UI 内置 Icon name-->
|
||||
<!--// 如果需要自定义 SVG,可以使用 custom-icon 插槽-->
|
||||
<!--const list = computed(() => [-->
|
||||
<!-- {-->
|
||||
<!-- pagePath: '/pages/index/index',-->
|
||||
<!-- text: '消息',-->
|
||||
<!-- icon: 'chat', // 对应 wd-icon name="chat"-->
|
||||
<!-- badge: appStore.unreadCount || 0-->
|
||||
<!-- },-->
|
||||
<!-- {-->
|
||||
<!-- pagePath: '/pages/contact/index',-->
|
||||
<!-- text: '通讯录',-->
|
||||
<!-- icon: 'user-circle', // 对应 wd-icon name="user-circle"-->
|
||||
<!-- badge: appStore.contactUnread || 0-->
|
||||
<!-- },-->
|
||||
<!-- {-->
|
||||
<!-- pagePath: '/pages/moment/index',-->
|
||||
<!-- text: '发现',-->
|
||||
<!-- icon: 'camera', // 对应 wd-icon name="camera"-->
|
||||
<!-- badge: appStore.momentUnread ? 1 : 0-->
|
||||
<!-- },-->
|
||||
<!-- {-->
|
||||
<!-- pagePath: '/pages/profile/index',-->
|
||||
<!-- text: '我的',-->
|
||||
<!-- icon: 'user', // 对应 wd-icon name="user"-->
|
||||
<!-- badge: 0-->
|
||||
<!-- }-->
|
||||
<!--])-->
|
||||
|
||||
<!--const current = computed(() => {-->
|
||||
<!-- if (props.active) return props.active-->
|
||||
<!-- const pages = getCurrentPages()-->
|
||||
<!-- const page = pages[pages.length - 1]-->
|
||||
<!-- return '/' + page.route-->
|
||||
<!--})-->
|
||||
|
||||
<!--function handleChange({ value }: { value: string }) {-->
|
||||
<!-- uni.switchTab({ url: value })-->
|
||||
<!--}-->
|
||||
<!--</script>-->
|
||||
|
||||
<!--<style lang="scss" scoped>-->
|
||||
<!--:deep(.app-tab-bar) {-->
|
||||
<!-- background-color: var(--bg-content) !important;-->
|
||||
|
||||
<!-- // 覆盖选中态颜色,保持与原有设计一致-->
|
||||
<!-- .wd-tabbar-item.is-active {-->
|
||||
<!-- color: var(--color-primary) !important;-->
|
||||
<!-- }-->
|
||||
<!--}-->
|
||||
|
||||
<!--.dark {-->
|
||||
<!-- :deep(.app-tab-bar) {-->
|
||||
<!-- background-color: #1c1c1e !important;-->
|
||||
<!-- border-top-color: #333;-->
|
||||
|
||||
<!-- .wd-tabbar-item {-->
|
||||
<!-- color: var(--text-secondary);-->
|
||||
<!-- &.is-active {-->
|
||||
<!-- color: var(--color-primary);-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!-- }-->
|
||||
<!--}-->
|
||||
<!--</style>-->
|
||||
<!--*/-->
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,52 +1,62 @@
|
||||
<template>
|
||||
<!-- 根节点绑定 dark class 适配全局暗黑模式 -->
|
||||
<view class="login-page" :class="{ dark: isDark }">
|
||||
<!-- 导航栏 -->
|
||||
<app-nav-bar title="登录" :left-arrow="false" />
|
||||
<app-nav-bar title="登录" :left-arrow="false" :bordered="false" />
|
||||
|
||||
<!-- Logo -->
|
||||
<!-- Logo 区域 -->
|
||||
<view class="logo-section">
|
||||
<view class="logo">
|
||||
<wd-icon name="chat" size="120rpx" color="#07c160" />
|
||||
<view class="logo-box">
|
||||
<wd-icon name="chat" size="60px" color="#07c160" />
|
||||
</view>
|
||||
<text class="app-name">NL-IM</text>
|
||||
<text class="app-desc">即时通讯</text>
|
||||
<text class="app-desc">即时通讯,连接你我</text>
|
||||
</view>
|
||||
|
||||
<!-- 登录表单 -->
|
||||
<!-- 表单区域 -->
|
||||
<view class="form-section">
|
||||
<wd-cell-group border>
|
||||
<wd-input
|
||||
v-model="form.account"
|
||||
label="账号"
|
||||
placeholder="请输入手机号/邮箱"
|
||||
clearable
|
||||
:prefix-icon="'user'"
|
||||
v-model="form.account"
|
||||
size="large"
|
||||
label="账号"
|
||||
label-width="60px"
|
||||
placeholder="请输入手机号/邮箱"
|
||||
clearable
|
||||
prefix-icon="user"
|
||||
:placeholder-style="isDark ? 'color: #555' : ''"
|
||||
/>
|
||||
<wd-input
|
||||
v-model="form.password"
|
||||
label="密码"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
clearable
|
||||
show-password
|
||||
:prefix-icon="'lock'"
|
||||
v-model="form.password"
|
||||
size="large"
|
||||
label="密码"
|
||||
label-width="60px"
|
||||
type="password"
|
||||
placeholder="请输入密码"
|
||||
clearable
|
||||
show-password
|
||||
prefix-icon="lock"
|
||||
:placeholder-style="isDark ? 'color: #555' : ''"
|
||||
/>
|
||||
</wd-cell-group>
|
||||
|
||||
<view class="form-options">
|
||||
<wd-checkbox v-model="form.remember">记住登录</wd-checkbox>
|
||||
<wd-checkbox v-model="form.remember" shape="square">记住登录</wd-checkbox>
|
||||
<text class="forgot-link" @click="forgotPassword">忘记密码?</text>
|
||||
</view>
|
||||
|
||||
<wd-button
|
||||
type="primary"
|
||||
block
|
||||
:loading="loading"
|
||||
:disabled="!canLogin"
|
||||
@click="handleLogin"
|
||||
>
|
||||
登录
|
||||
</wd-button>
|
||||
<view class="action-buttons">
|
||||
<wd-button
|
||||
type="primary"
|
||||
block
|
||||
size="large"
|
||||
:loading="loading"
|
||||
:disabled="!canLogin"
|
||||
@click="handleLogin"
|
||||
>
|
||||
登录
|
||||
</wd-button>
|
||||
</view>
|
||||
|
||||
<view class="register-link">
|
||||
<text>还没有账号?</text>
|
||||
@@ -56,19 +66,16 @@
|
||||
|
||||
<!-- 其他登录方式 -->
|
||||
<view class="other-login">
|
||||
<view class="divider">
|
||||
<view class="line" />
|
||||
<text class="text">其他登录方式</text>
|
||||
<view class="line" />
|
||||
</view>
|
||||
<wd-divider color="var(--text-tertiary)">其他登录方式</wd-divider>
|
||||
|
||||
<view class="login-icons">
|
||||
<view class="login-icon" @click="loginWithWeixin">
|
||||
<wd-icon name="weixin" size="56rpx" color="#07c160" />
|
||||
<view class="login-icon-item" hover-class="hover-opacity" @click="loginWithWeixin">
|
||||
<wd-icon name="weixin" size="32px" color="#07c160" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- Toast 和 MessageBox -->
|
||||
<!-- 全局反馈组件 -->
|
||||
<wd-toast />
|
||||
<wd-message-box />
|
||||
</view>
|
||||
@@ -79,6 +86,8 @@ import { ref, computed } from 'vue'
|
||||
import { useAuthStore } from '@/stores'
|
||||
import { useToast, useMessage } from 'wot-design-uni'
|
||||
import { useTheme } from '@/composables/useTheme'
|
||||
// 引入 AppNavBar 组件 (通常已自动引入,显式引入以防万一)
|
||||
import AppNavBar from '@/components/common/AppNavBar.vue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const toast = useToast()
|
||||
@@ -99,7 +108,7 @@ const canLogin = computed(() => {
|
||||
return form.value.account.trim() && form.value.password.trim()
|
||||
})
|
||||
|
||||
// 登录
|
||||
// 登录逻辑 (保持原有逻辑不变)
|
||||
async function handleLogin() {
|
||||
if (!canLogin.value) return
|
||||
|
||||
@@ -121,17 +130,14 @@ async function handleLogin() {
|
||||
}
|
||||
}
|
||||
|
||||
// 忘记密码
|
||||
function forgotPassword() {
|
||||
toast.show('忘记密码功能开发中')
|
||||
}
|
||||
|
||||
// 去注册
|
||||
function goRegister() {
|
||||
toast.show('注册功能开发中')
|
||||
}
|
||||
|
||||
// 微信登录
|
||||
function loginWithWeixin() {
|
||||
// #ifdef MP-WEIXIN
|
||||
uni.login({
|
||||
@@ -157,55 +163,55 @@ function loginWithWeixin() {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background: var(--bg-page);
|
||||
background-color: var(--bg-page);
|
||||
padding: 0 40rpx;
|
||||
box-sizing: border-box;
|
||||
transition: background-color 0.3s;
|
||||
}
|
||||
|
||||
// Logo 区域
|
||||
.logo-section {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 150rpx;
|
||||
padding-top: 120rpx;
|
||||
margin-bottom: 80rpx;
|
||||
|
||||
.logo {
|
||||
.logo-box {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--bg-content);
|
||||
background-color: var(--bg-content);
|
||||
border-radius: 32rpx;
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.1);
|
||||
box-shadow: 0 8rpx 32rpx rgba(0, 0, 0, 0.05);
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.app-name {
|
||||
margin-top: 24rpx;
|
||||
font-size: 48rpx;
|
||||
font-weight: 700;
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.app-desc {
|
||||
margin-top: 8rpx;
|
||||
margin-top: 12rpx;
|
||||
font-size: 28rpx;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
}
|
||||
|
||||
// 表单区域
|
||||
.form-section {
|
||||
background: var(--bg-content);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
margin-bottom: 40rpx;
|
||||
background-color: var(--bg-content);
|
||||
border-radius: 24rpx;
|
||||
padding: 40rpx 30rpx;
|
||||
box-shadow: 0 4rpx 24rpx rgba(0, 0, 0, 0.02);
|
||||
|
||||
.form-options {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 30rpx 0;
|
||||
margin: 30rpx 0 50rpx;
|
||||
|
||||
.forgot-link {
|
||||
font-size: 28rpx;
|
||||
@@ -213,56 +219,46 @@ function loginWithWeixin() {
|
||||
}
|
||||
}
|
||||
|
||||
.action-buttons {
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
|
||||
.register-link {
|
||||
text-align: center;
|
||||
margin-top: 30rpx;
|
||||
font-size: 28rpx;
|
||||
color: var(--text-secondary);
|
||||
|
||||
.link {
|
||||
color: var(--color-primary);
|
||||
margin-left: 8rpx;
|
||||
margin-left: 10rpx;
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 其他登录方式
|
||||
.other-login {
|
||||
margin-top: auto;
|
||||
padding-bottom: calc(60rpx + env(safe-area-inset-bottom));
|
||||
|
||||
.divider {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 40rpx;
|
||||
|
||||
.line {
|
||||
flex: 1;
|
||||
height: 1rpx;
|
||||
background: var(--border-color);
|
||||
}
|
||||
|
||||
.text {
|
||||
padding: 0 24rpx;
|
||||
font-size: 26rpx;
|
||||
color: var(--text-tertiary);
|
||||
}
|
||||
}
|
||||
width: 100%;
|
||||
|
||||
.login-icons {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
gap: 60rpx;
|
||||
margin-top: 40rpx;
|
||||
|
||||
.login-icon {
|
||||
.login-icon-item {
|
||||
width: 96rpx;
|
||||
height: 96rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
background: var(--bg-content);
|
||||
background-color: var(--bg-content);
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.08);
|
||||
box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
|
||||
|
||||
&.hover-opacity {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,115 +1,138 @@
|
||||
<template>
|
||||
<view class="profile-page" :class="{ dark: isDark }">
|
||||
<!-- 导航栏 -->
|
||||
<app-nav-bar title="个人资料" />
|
||||
<!-- 顶部导航栏 (透明背景或自定义颜色) -->
|
||||
<app-nav-bar title="" :left-arrow="false" :bordered="false" />
|
||||
|
||||
<!-- 头像区域 -->
|
||||
<view class="header-section">
|
||||
<view class="avatar-wrap" @click="changeAvatar">
|
||||
<app-avatar
|
||||
:src="user?.avatar"
|
||||
:name="user?.name"
|
||||
:size="160"
|
||||
round
|
||||
<!-- 用户信息卡片 -->
|
||||
<view class="user-card" @click="goProfileEdit">
|
||||
<view class="avatar-wrapper">
|
||||
<wd-img
|
||||
:src="userInfo.avatar"
|
||||
width="120rpx"
|
||||
height="120rpx"
|
||||
round
|
||||
mode="aspectFill"
|
||||
/>
|
||||
<view class="change-tip">点击更换</view>
|
||||
</view>
|
||||
<view class="info-wrapper">
|
||||
<view class="name-row">
|
||||
<text class="nickname">{{ userInfo.nickname || '未设置昵称' }}</text>
|
||||
<wd-icon name="edit" size="16px" color="var(--text-secondary)" custom-class="edit-icon" />
|
||||
</view>
|
||||
<text class="account">账号: {{ userInfo.account || '--' }}</text>
|
||||
</view>
|
||||
<view class="arrow">
|
||||
<wd-icon name="arrow-right" color="var(--text-tertiary)" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 基本信息 -->
|
||||
<wd-cell-group title="基本信息">
|
||||
<wd-cell title="昵称" :value="user?.name || '未设置'" is-link @click="editField('name')" />
|
||||
<wd-cell title="ID" :value="user?.id || '-'" />
|
||||
<wd-cell title="个性签名" :value="user?.desc || '未设置'" is-link @click="editField('desc')" />
|
||||
<wd-cell title="地区" :value="user?.region || '未设置'" is-link @click="editField('region')" />
|
||||
</wd-cell-group>
|
||||
<!-- 功能列表 -->
|
||||
<view class="menu-list">
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="我的动态" is-link to="/pages/moment/my" icon="moments" size="large" />
|
||||
<wd-cell title="收藏夹" is-link to="/pages/collection/index" icon="star" size="large" />
|
||||
<wd-cell title="相册" is-link to="/pages/album/index" icon="picture" size="large" />
|
||||
</wd-cell-group>
|
||||
|
||||
<!-- 联系方式 -->
|
||||
<wd-cell-group title="联系方式">
|
||||
<wd-cell title="手机号" :value="formatPhone(user?.phone)" />
|
||||
<wd-cell title="邮箱" :value="user?.email || '未绑定'" />
|
||||
</wd-cell-group>
|
||||
<view class="gap" />
|
||||
|
||||
<wd-toast />
|
||||
<wd-cell-group border>
|
||||
<wd-cell title="设置" is-link to="/pages/settings/index" icon="setting" size="large" />
|
||||
</wd-cell-group>
|
||||
</view>
|
||||
|
||||
<!-- 底部 TabBar -->
|
||||
<app-tab-bar active="/pages/profile/index" />
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { useAuthStore } from '@/stores'
|
||||
import { useToast } from 'wot-design-uni'
|
||||
import { useTheme } from '@/composables/useTheme'
|
||||
import { resolveImageUrl } from '@/utils/image'
|
||||
import AppAvatar from '@/components/common/AppAvatar.vue'
|
||||
import { useAuthStore } from '@/stores'
|
||||
import AppNavBar from '@/components/common/AppNavBar.vue'
|
||||
import AppTabBar from '@/components/common/AppTabBar.vue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const toast = useToast()
|
||||
const { isDark } = useTheme()
|
||||
const authStore = useAuthStore()
|
||||
|
||||
const user = computed(() => authStore.user)
|
||||
const userInfo = computed(() => authStore.userInfo || {})
|
||||
|
||||
function formatPhone(phone?: string) {
|
||||
if (!phone) return '未绑定'
|
||||
return phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2')
|
||||
}
|
||||
|
||||
function changeAvatar() {
|
||||
uni.chooseImage({
|
||||
count: 1,
|
||||
sizeType: ['compressed'],
|
||||
sourceType: ['album', 'camera'],
|
||||
success: (res) => {
|
||||
// TODO: 上传头像
|
||||
console.log('选择的图片:', res.tempFilePaths[0])
|
||||
toast.show('头像上传功能开发中')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function editField(field: string) {
|
||||
const value = field === 'name' ? user.value?.name : field === 'desc' ? user.value?.desc : user.value?.region
|
||||
uni.navigateTo({
|
||||
url: `/pages/profile/edit?field=${field}&value=${encodeURIComponent(value || '')}`
|
||||
})
|
||||
function goProfileEdit() {
|
||||
uni.navigateTo({ url: '/pages/profile/edit' })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.profile-page {
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
background-color: var(--bg-page);
|
||||
padding-bottom: calc(100rpx + env(safe-area-inset-bottom));
|
||||
}
|
||||
|
||||
.header-section {
|
||||
.user-card {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
padding: 60rpx 0;
|
||||
background: var(--bg-content);
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
|
||||
.avatar-wrap {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 40rpx 32rpx;
|
||||
background-color: var(--bg-content);
|
||||
margin-bottom: 24rpx;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
.avatar-placeholder {
|
||||
width: 160rpx;
|
||||
height: 160rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border-radius: 50%;
|
||||
background: var(--color-primary);
|
||||
color: #fff;
|
||||
font-size: 64rpx;
|
||||
font-weight: 600;
|
||||
&:active {
|
||||
background-color: var(--bg-active);
|
||||
}
|
||||
|
||||
.change-tip {
|
||||
margin-top: 16rpx;
|
||||
font-size: 26rpx;
|
||||
color: var(--text-tertiary);
|
||||
.avatar-wrapper {
|
||||
margin-right: 32rpx;
|
||||
border: 2rpx solid var(--border-color);
|
||||
border-radius: 50%;
|
||||
padding: 2rpx; // 模拟头像边框
|
||||
}
|
||||
|
||||
.info-wrapper {
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
|
||||
.name-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 12rpx;
|
||||
|
||||
.nickname {
|
||||
font-size: 40rpx;
|
||||
font-weight: 600;
|
||||
color: var(--text-primary);
|
||||
margin-right: 12rpx;
|
||||
}
|
||||
|
||||
.edit-icon {
|
||||
opacity: 0.6;
|
||||
}
|
||||
}
|
||||
|
||||
.account {
|
||||
font-size: 28rpx;
|
||||
color: var(--text-secondary);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-list {
|
||||
.gap {
|
||||
height: 24rpx;
|
||||
}
|
||||
}
|
||||
|
||||
.dark {
|
||||
.user-card {
|
||||
background-color: var(--bg-content);
|
||||
}
|
||||
|
||||
:deep(.wd-cell) {
|
||||
background-color: var(--bg-content);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,29 +1,32 @@
|
||||
<template>
|
||||
<view class="settings-page" :class="{ dark: isDark }">
|
||||
<!-- 导航栏 -->
|
||||
<app-nav-bar title="设置" />
|
||||
|
||||
<wd-cell-group title="账号设置">
|
||||
<wd-cell title="个人资料" icon="user" is-link @click="goProfile" />
|
||||
<wd-cell title="账号与安全" icon="shield" is-link @click="goSecurity" />
|
||||
</wd-cell-group>
|
||||
<view class="content">
|
||||
<!-- 账号安全 -->
|
||||
<wd-cell-group title="账号安全" border>
|
||||
<wd-cell title="账号管理" is-link to="/pages/settings/account" />
|
||||
<wd-cell title="隐私设置" is-link to="/pages/settings/privacy" />
|
||||
</wd-cell-group>
|
||||
|
||||
<wd-cell-group title="通用设置">
|
||||
<wd-cell title="消息通知" icon="bell" is-link @click="goNotification" />
|
||||
<wd-cell title="隐私设置" icon="eye-close" is-link @click="goPrivacy" />
|
||||
<wd-cell title="深色模式" icon="picture" :value="themeText" is-link @click="goTheme" />
|
||||
<wd-cell title="清除缓存" icon="delete" :value="cacheSize" is-link @click="clearCache" />
|
||||
</wd-cell-group>
|
||||
<!-- 通用设置 -->
|
||||
<wd-cell-group title="通用" border>
|
||||
<wd-cell title="新消息通知" is-link to="/pages/settings/notification" />
|
||||
<wd-cell title="主题设置" is-link to="/pages/settings/theme" value="自动" />
|
||||
<wd-cell title="通用设置" is-link to="/pages/settings/general" />
|
||||
<wd-cell title="清理缓存" is-link value="12.5MB" clickable @click="handleClearCache" />
|
||||
</wd-cell-group>
|
||||
|
||||
<wd-cell-group title="关于">
|
||||
<wd-cell title="当前版本" value="v1.0.0" />
|
||||
<wd-cell title="用户协议" is-link @click="goAgreement" />
|
||||
<wd-cell title="隐私政策" is-link @click="goPrivacyPolicy" />
|
||||
<wd-cell title="检查更新" is-link @click="checkUpdate" />
|
||||
</wd-cell-group>
|
||||
<!-- 关于 -->
|
||||
<wd-cell-group title="关于" border>
|
||||
<wd-cell title="帮助与反馈" is-link to="/pages/settings/feedback" />
|
||||
<wd-cell title="关于我们" is-link to="/pages/settings/about" value="v1.0.0" />
|
||||
</wd-cell-group>
|
||||
|
||||
<view class="logout-section">
|
||||
<wd-button type="error" block plain @click="logout">退出登录</wd-button>
|
||||
<!-- 退出登录 -->
|
||||
<view class="logout-section">
|
||||
<wd-button type="error" block size="large" @click="handleLogout">退出登录</wd-button>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<wd-toast />
|
||||
@@ -32,128 +35,68 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useAuthStore } from '@/stores'
|
||||
import { useTheme } from '@/composables/useTheme'
|
||||
import { useAuthStore } from '@/stores'
|
||||
import { useToast, useMessage } from 'wot-design-uni'
|
||||
import AppNavBar from '@/components/common/AppNavBar.vue'
|
||||
|
||||
const authStore = useAuthStore()
|
||||
const { isDark } = useTheme()
|
||||
const authStore = useAuthStore()
|
||||
const toast = useToast()
|
||||
const messageBox = useMessage()
|
||||
const message = useMessage()
|
||||
|
||||
const cacheSize = ref('0 KB')
|
||||
|
||||
// 主题显示文本
|
||||
const themeText = computed(() => {
|
||||
const mode = uni.getStorageSync('nl_im_theme_mode') || 'system'
|
||||
const texts: Record<string, string> = {
|
||||
system: '跟随系统',
|
||||
light: '浅色模式',
|
||||
dark: '深色模式'
|
||||
}
|
||||
return texts[mode] || '跟随系统'
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
calculateCacheSize()
|
||||
})
|
||||
|
||||
function calculateCacheSize() {
|
||||
try {
|
||||
const info = uni.getStorageInfoSync()
|
||||
const size = info.currentSize || 0
|
||||
if (size < 1024) {
|
||||
cacheSize.value = `${size} KB`
|
||||
} else {
|
||||
cacheSize.value = `${(size / 1024).toFixed(2)} MB`
|
||||
function handleLogout() {
|
||||
message.confirm({
|
||||
title: '提示',
|
||||
msg: '确定要退出登录吗?',
|
||||
success: async () => {
|
||||
try {
|
||||
await authStore.logout()
|
||||
uni.reLaunch({ url: '/pages/login/index' })
|
||||
} catch (error) {
|
||||
toast.error('退出失败')
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
cacheSize.value = '0 KB'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function goProfile() {
|
||||
uni.navigateTo({ url: '/pages/profile/index' })
|
||||
}
|
||||
|
||||
function goSecurity() {
|
||||
toast.show('账号安全功能开发中')
|
||||
}
|
||||
|
||||
function goNotification() {
|
||||
toast.show('消息通知设置开发中')
|
||||
}
|
||||
|
||||
function goPrivacy() {
|
||||
toast.show('隐私设置功能开发中')
|
||||
}
|
||||
|
||||
function goTheme() {
|
||||
uni.navigateTo({ url: '/pages/settings/theme' })
|
||||
}
|
||||
|
||||
async function clearCache() {
|
||||
try {
|
||||
await messageBox.confirm({
|
||||
title: '提示',
|
||||
msg: '确定要清除缓存吗?'
|
||||
})
|
||||
|
||||
// 保留登录信息
|
||||
const token = uni.getStorageSync('nl_im_token')
|
||||
const userId = uni.getStorageSync('nl_im_user_id')
|
||||
const userInfo = uni.getStorageSync('nl_im_user_info')
|
||||
const theme = uni.getStorageSync('nl_im_theme')
|
||||
|
||||
uni.clearStorageSync()
|
||||
|
||||
// 恢复登录信息
|
||||
if (token) uni.setStorageSync('nl_im_token', token)
|
||||
if (userId) uni.setStorageSync('nl_im_user_id', userId)
|
||||
if (userInfo) uni.setStorageSync('nl_im_user_info', userInfo)
|
||||
if (theme) uni.setStorageSync('nl_im_theme', theme)
|
||||
|
||||
cacheSize.value = '0 KB'
|
||||
toast.success('清除成功')
|
||||
} catch {
|
||||
// 取消
|
||||
}
|
||||
}
|
||||
|
||||
function goAgreement() {
|
||||
toast.show('用户协议页面开发中')
|
||||
}
|
||||
|
||||
function goPrivacyPolicy() {
|
||||
toast.show('隐私政策页面开发中')
|
||||
}
|
||||
|
||||
function checkUpdate() {
|
||||
toast.show('当前已是最新版本')
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
try {
|
||||
await messageBox.confirm({
|
||||
title: '提示',
|
||||
msg: '确定要退出登录吗?'
|
||||
})
|
||||
authStore.logout()
|
||||
} catch {
|
||||
// 取消
|
||||
}
|
||||
function handleClearCache() {
|
||||
toast.loading('清理中...')
|
||||
setTimeout(() => {
|
||||
toast.success('清理完成')
|
||||
}, 1000)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.settings-page {
|
||||
min-height: 100vh;
|
||||
background: var(--bg-page);
|
||||
background-color: var(--bg-page);
|
||||
|
||||
.content {
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
.logout-section {
|
||||
margin: 60rpx 30rpx 0;
|
||||
}
|
||||
}
|
||||
|
||||
.logout-section {
|
||||
padding: 60rpx 30rpx;
|
||||
padding-bottom: calc(60rpx + env(safe-area-inset-bottom));
|
||||
// 暗黑模式微调 Cell Group 标题颜色
|
||||
.dark {
|
||||
:deep(.wd-cell-group__title) {
|
||||
color: var(--text-secondary);
|
||||
background-color: var(--bg-page);
|
||||
}
|
||||
|
||||
:deep(.wd-cell) {
|
||||
background-color: var(--bg-content);
|
||||
color: var(--text-primary);
|
||||
|
||||
// 覆盖 cell 内部线条颜色 (如果需要)
|
||||
&::after {
|
||||
background-color: var(--border-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user