1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-07-27 04:20:43 +08:00
Files
uni-halo/src/pages/mine/mine.vue
T
小莫唐尼 a9e649e110 feat: 新增点赞、游客评论、分享等核心功能,重构页面逻辑
1. 新增全局点赞状态管理,使用metadata.name做key并持久化存储
2. 新增游客信息存储与评论面板,支持游客评论互动
3. 新增全局分享hook,为多个页面配置分享功能
4. 重构登录页面,支持登录/注册切换与游客访问模式
5. 合并注册页到登录页,简化路由结构
6. 优化剪贴板工具函数,支持自定义提示文本
7. 重构个人中心页面,支持游客信息管理
8. 修复相册页面标题与样式问题
9. 移除无用的备份文件与测试代码
2026-06-16 00:43:48 +08:00

231 lines
6.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
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.
<script lang="ts" setup>
import { storeToRefs } from 'pinia'
import { LOGIN_PAGE } from '@/router/config'
import { useUserStore } from '@/store'
import { useGuestStore } from '@/store/guest'
import { useTokenStore } from '@/store/token'
import GuestInfoPanel from '@/components/post-detail/uh-guest-info-panel.vue'
defineOptions({ name: 'Mine' })
definePage({
style: {
navigationBarTitleText: '我的',
navigationBarBackgroundColor: '#ffffff',
},
})
const userStore = useUserStore()
const tokenStore = useTokenStore()
const guestStore = useGuestStore()
const { userInfo } = storeToRefs(userStore)
/** 是否已登录 */
const hasLogin = computed(() => tokenStore.hasLogin)
/** 是否已填写游客信息 */
const hasGuestInfo = computed(() => guestStore.isComplete)
/** 显示的头像 */
const displayAvatar = computed(() => {
if (hasLogin.value && userInfo.value.avatar) {
return userInfo.value.avatar
}
return '/static/images/default-avatar.png'
})
/** 显示的名称 */
const displayName = computed(() => {
if (hasLogin.value) {
return userInfo.value.nickname || userInfo.value.username
}
if (hasGuestInfo.value) {
return guestStore.info.displayName
}
return '未登录'
})
/** 显示的副标题 */
const displaySubtitle = computed(() => {
if (hasLogin.value) {
return userInfo.value.role || userInfo.value.username
}
if (hasGuestInfo.value) {
return guestStore.info.email
}
return '登录后解锁更多功能'
})
/** 用户状态标签 */
const statusLabel = computed(() => {
if (hasLogin.value) return '已登录'
if (hasGuestInfo.value) return '游客'
return '未登录'
})
const statusColor = computed(() => {
if (hasLogin.value) return 'bg-green-50 text-green-600'
if (hasGuestInfo.value) return 'bg-amber-50 text-amber-600'
return 'bg-gray-100 text-gray-500'
})
// ---- 游客信息编辑 ----
const showGuestPanel = ref(false)
function handleEditGuest() {
showGuestPanel.value = true
}
function handleGuestSaved() {
showGuestPanel.value = false
uni.showToast({ title: '保存成功', icon: 'success' })
}
// ---- 登录/退出 ----
function handleLogin() {
// #ifdef MP-WEIXIN
tokenStore.wxLogin()
// #endif
// #ifndef MP-WEIXIN
uni.navigateTo({ url: LOGIN_PAGE })
// #endif
}
function handleLogout() {
uni.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
tokenStore.logout()
uni.showToast({ title: '已退出登录', icon: 'success' })
}
},
})
}
// ---- 功能导航 ----
interface NavItem {
icon: string
label: string
path?: string
showArrow?: boolean
}
const navList: NavItem[] = [
{ icon: 'file', label: '免责声明', path: '', showArrow: true },
{ icon: 'chat', label: '在线客服', path: '', showArrow: true },
{ icon: 'edit', label: '意见反馈', path: '', showArrow: true },
{ icon: 'info-circle', label: '关于项目', path: '/subpkg-blog/about/about', showArrow: true },
]
function handleNavClick(item: NavItem) {
if (item.path) {
uni.navigateTo({ url: item.path })
}
else {
uni.showToast({ title: '即将开放,敬请期待', icon: 'none' })
}
}
</script>
<template>
<view class="bg-page3 box-border min-h-screen w-full flex flex-col gap-y-4 px-4 pt-4">
<!-- 用户信息卡片 -->
<view class="uh-shadow-xs box-border flex flex-col rounded-2xl bg-white p-4">
<view class="w-full flex items-center gap-x-3">
<!-- 头像 -->
<image
class="uh-shadow-xs h-16 w-16 shrink-0 border-2 border-white rounded-full border-solid"
:src="displayAvatar"
mode="scaleToFill"
/>
<!-- 信息区 -->
<view class="flex flex-1 flex-col gap-y-1">
<view class="flex items-center gap-x-2">
<text class="text-base text-gray-900 font-bold">{{ displayName }}</text>
<view class="rounded-full px-2 py-0.5" :class="statusColor">
<text class="text-[10px] font-medium">{{ statusLabel }}</text>
</view>
</view>
<text class="line-clamp-1 text-xs text-gray-500">{{ displaySubtitle }}</text>
</view>
<!-- 游客编辑入口 -->
<view
v-if="!hasLogin && hasGuestInfo"
class="h-8 w-8 center shrink-0 rounded-full bg-gray-50"
@click="handleEditGuest"
>
<wd-icon name="edit" color="#6B7280" :size="16" />
</view>
</view>
<!-- 游客信息快捷编辑入口未登录且未填写游客信息时 -->
<view
v-if="!hasLogin && !hasGuestInfo"
class="mt-3 box-border flex items-center gap-x-2 rounded-xl bg-gray-50 px-3 py-2.5"
@click="handleEditGuest"
>
<wd-icon name="edit" color="#9CA3AF" :size="14" />
<text class="text-xs text-gray-400">填写游客信息用于评论互动</text>
<wd-icon name="arrow-right" color="#D1D5DB" :size="14" />
</view>
<!-- 已登录时显示的额外信息 -->
<view v-if="hasLogin" class="mt-3 my-1 h-px w-full bg-gray-50" />
<view v-if="hasLogin" class="flex items-center justify-between">
<text class="text-xs text-gray-400">账号{{ userInfo.username }}</text>
</view>
</view>
<!-- 功能导航 -->
<view class="uh-shadow-xs box-border flex flex-col rounded-2xl bg-white">
<view
v-for="(item, index) in navList"
:key="item.label"
class="box-border flex items-center justify-between px-4 py-3.5"
:class="{ 'border-b border-gray-50': index < navList.length - 1 }"
@click="handleNavClick(item)"
>
<view class="flex items-center gap-x-3">
<view class="h-8 w-8 center rounded-xl bg-gray-50">
<wd-icon :name="item.icon" color="#6B7280" :size="16" />
</view>
<text class="text-sm text-gray-800">{{ item.label }}</text>
</view>
<wd-icon v-if="item.showArrow" name="arrow-right" color="#D1D5DB" :size="14" />
</view>
</view>
<!-- 登录/退出按钮 -->
<view class="mt-2 w-full">
<view
v-if="hasLogin"
class="uh-shadow-xs h-11 w-full center rounded-2xl bg-white text-sm text-red-500 font-medium"
@click="handleLogout"
>
退出登录
</view>
<view
v-else
class="h-11 w-full center rounded-2xl bg-gray-900 text-sm text-white font-medium"
@click="handleLogin"
>
立即登录
</view>
</view>
<!-- 底部导航占位 -->
<view class="w-full shrink-0">
<uh-tabbar-page-placeholder />
</view>
<!-- 游客信息编辑面板 -->
<GuestInfoPanel
v-if="showGuestPanel"
@close="showGuestPanel = false"
@saved="handleGuestSaved"
/>
</view>
</template>