1
0
mirror of https://github.com/ialley-workshop-open/uni-halo.git synced 2026-07-27 04:20:43 +08:00

feat: 新增点赞、游客评论、分享等核心功能,重构页面逻辑

1. 新增全局点赞状态管理,使用metadata.name做key并持久化存储
2. 新增游客信息存储与评论面板,支持游客评论互动
3. 新增全局分享hook,为多个页面配置分享功能
4. 重构登录页面,支持登录/注册切换与游客访问模式
5. 合并注册页到登录页,简化路由结构
6. 优化剪贴板工具函数,支持自定义提示文本
7. 重构个人中心页面,支持游客信息管理
8. 修复相册页面标题与样式问题
9. 移除无用的备份文件与测试代码
This commit is contained in:
小莫唐尼
2026-06-16 00:43:48 +08:00
parent 1ba71ff43f
commit a9e649e110
19 changed files with 1077 additions and 597 deletions
+176 -87
View File
@@ -2,38 +2,92 @@
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 i18n, { t } from '@/locale/index'
import { setTabbarItem } from '@/tabbar/i18n'
import GuestInfoPanel from '@/components/post-detail/uh-guest-info-panel.vue'
defineOptions({
name: 'Mine',
})
defineOptions({ name: 'Mine' })
definePage({
style: {
navigationBarTitleText: '我的',
navigationBarBackgroundColor: '#ffffff',
enablePullDownRefresh: true,
},
})
const userStore = useUserStore()
const tokenStore = useTokenStore()
// 使用storeToRefs解构userInfo
const guestStore = useGuestStore()
const { userInfo } = storeToRefs(userStore)
// 微信小程序下登录
async function handleLogin() {
// #ifdef MP-WEIXIN
// 微信登录
await tokenStore.wxLogin()
/** 是否已登录 */
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}`,
})
uni.navigateTo({ url: LOGIN_PAGE })
// #endif
}
@@ -43,93 +97,121 @@ function handleLogout() {
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
// 清空用户信息
useTokenStore().logout()
// 执行退出登录逻辑
uni.showToast({
title: '退出登录成功',
icon: 'success',
})
// #ifdef MP-WEIXIN
// 微信小程序,去首页
// uni.reLaunch({ url: '/pages/index/index' })
// #endif
// #ifndef MP-WEIXIN
// 非微信小程序,去登录页
// uni.navigateTo({ url: LOGIN_PAGE })
// #endif
tokenStore.logout()
uni.showToast({ title: '已退出登录', icon: 'success' })
}
},
})
}
const current = ref(uni.getLocale())
const languages = [
{
value: 'zh-Hans',
name: '中文',
checked: 'true',
},
{
value: 'en',
name: '英文',
},
// ---- 功能导航 ----
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 radioChange(evt) {
// console.log(evt)
current.value = evt.detail.value
// 下面2句缺一不可!!!
uni.setLocale(evt.detail.value)
i18n.global.locale = evt.detail.value
// 底部tabbar需要重新设置一下
setTabbarItem()
// 本页的标题也需要重新设置一下
uni.setNavigationBarTitle({
title: t('i18n.title'),
})
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 items-center justify-center gap-y-6 px-4">
<view class="mt-3 break-all px-3 text-center text-green-500">
{{ userInfo.username ? '已登录' : '未登录' }}
</view>
<view class="mt-3 break-all px-3">
{{ JSON.stringify(userInfo, null, 2) }}
</view>
<!-- 切换语言 -->
<view class="mt-6 w-full flex flex-col items-center justify-center">
<view class="mb-2 text-gray-900 font-bold">
切换语言
</view>
<view class="w-full flex items-center justify-center gap-4">
<radio-group class="flex flex-col items-center justify-center gap-2" @change="radioChange">
<label
v-for="item in languages"
:key="item.value"
class="flex items-center gap-x-2"
>
<view>
<radio :value="item.value" :checked="item.value === current" />
<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>{{ item.name }}</view>
</label>
</radio-group>
</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="mt-6">
<view class="m-auto w-160px text-center">
<button v-if="tokenStore.hasLogin" type="warn" class="w-full rounded-xl text-xs" @click="handleLogout">
退出登录
</button>
<button v-else class="w-full rounded-xl bg-gray-900 py-2.5 text-xs text-white" @click="handleLogin">
立即登录
</button>
<!-- 功能导航 -->
<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>
@@ -137,5 +219,12 @@ function radioChange(evt) {
<view class="w-full shrink-0">
<uh-tabbar-page-placeholder />
</view>
<!-- 游客信息编辑面板 -->
<GuestInfoPanel
v-if="showGuestPanel"
@close="showGuestPanel = false"
@saved="handleGuestSaved"
/>
</view>
</template>