Files
spring-festival-greetings/pages/mine/mine.vue
2026-01-09 11:24:40 +08:00

303 lines
7.2 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.
<template>
<view class="mine-content">
<!-- 顶部区域 -->
<view class="mine-top-panel" :style="{ paddingTop: getBavBarHeight() + 'px' }">
<view class="user-info">
<!-- 根据登录状态显示不同内容 -->
<view v-if="isLoggedIn" class="user-logged-in">
<image :src="userInfo.avatarUrl" class="avatar" mode="aspectFill" />
<view class="user-logged-in-info">
<text class="nickname">{{ userInfo.nickName }}</text>
<text class="phone">19969024553</text>
</view>
</view>
<view v-else class="user-not-logged-in">
<image :src="defaultAvatarUrl" class="avatar" mode="aspectFill" />
<button class="login-button" @tap="openPopup">点击登录</button>
</view>
</view>
</view>
<view class="mine-middle-panel">
<view class="mine-info-panel">
<view>0.00</view>
<view>我的余额</view>
</view>
<view class="mine-info-panel">
<view>0</view>
<view>优惠卷</view>
</view>
<view class="mine-info-panel">
<view>0</view>
<view>积分</view>
</view>
<view class="mine-info-panel">
<view>0</view>
<view>我的收藏</view>
</view>
</view>
<!-- 登录弹窗 -->
<uni-popup ref="popupRef" type="bottom" :safe-area="false">
<view class="popup-container">
<view class="popup-header">
<text class="popup-title">登录授权</text>
</view>
<view class="avatar-nickname">
<button open-type="chooseAvatar" @chooseavatar="onChooseAvatar" class="avatar-selector">
<image v-if="avatarUrl" :src="avatarUrl" class="avatar-preview" />
<text v-else>获取头像</text>
</button>
<input
class="nickname-input"
type="nickname"
v-model="nickname"
placeholder="请输入昵称"
/>
</view>
<button class="confirm-btn" @tap="confirmLogin">确认登录</button>
</view>
</uni-popup>
</view>
</template>
<script setup>
import { ref, computed, onMounted } from 'vue'
import { wxLogin } from '@/utils/login.js'
import { getPlatformProvider, getBavBarHeight } from '@/utils/system'
import { useUserStore } from '@/stores/user'
import { apiLogin } from '@/api/auth.js'
const userStore = useUserStore()
const popupRef = ref(null)
// 用户输入的临时信息
const avatarUrl = ref('')
const nickname = ref('')
// 从store获取用户信息改为计算属性
const userInfo = computed(() => ({
nickName: userStore.userInfo.nickName || '未登录',
avatarUrl: userStore.userInfo.avatarUrl || defaultAvatarUrl
}))
// 判断用户是否已登录
const isLoggedIn = computed(() => !!userStore.userInfo.nickName)
// 默认头像
const defaultAvatarUrl = 'https://file.lihailezzc.com/resource/d9b329082b32f8305101f708593a4882.png'
// 获取状态栏高度
const bavBarHeight = ref(0)
onMounted(() => {
// 确保高度值在组件挂载后获取
bavBarHeight.value = getBavBarHeight()
})
const openPopup = () => {
popupRef.value.open()
}
const onChooseAvatar = (e) => {
avatarUrl.value = e.detail.avatarUrl
}
const confirmLogin = async () => {
if (!nickname.value || !avatarUrl.value) {
return uni.showToast({ title: '请填写完整信息', icon: 'none' })
}
try {
const platform = getPlatformProvider()
if (platform === 'mp-weixin') {
const code = await wxLogin()
console.log('准备登录:', { code, nickname: nickname.value, avatarUrl: avatarUrl.value })
// console.log('准备登录:', { code, nickname: nickname.value, avatarUrl: 'http://tmp/HXhtcEwQ5A3B58476c91ba545ab67c6bf9c67d9c2559.jpeg' })
const fileKeyRes = await uni.uploadFile({
url: 'https://apis.lihailezzc.com/api/common/upload',
filePath: avatarUrl.value,
name: 'file', // 和后端接收文件字段名一致
header: {
'x-app-id': '6846f093fdf841f6189ef0b5',
},
})
if(fileKeyRes.statusCode < 400) {
const keyJson = JSON.parse(fileKeyRes.data)
const url = `https://file.lihailezzc.com/${keyJson?.data.key}`
const loginRes = await apiLogin({ code, nickname: nickname.value, avatarUrl: url })
// 保存用户信息到store
userStore.setUserInfo({
nickName: nickname.value,
avatarUrl: avatarUrl.value,
})
userStore.setToken(loginRes.token)
uni.showToast({ title: '登录成功', icon: 'success' })
popupRef.value.close()
// 重置临时变量
avatarUrl.value = ''
nickname.value = ''
} else {
throw Error('获取失败')
}
}
} catch (err) {
uni.showToast({ title: '登录失败', icon: 'none' })
console.error(err)
}
}
</script>
<style lang="scss">
.mine-content {
display: flex;
flex-direction: column;
align-items: center;
height: 100vh;
background: #F9F6F2;
button {
border: none;
outline: none;
background-color: transparent;
padding: 0;
margin: 0;
line-height: normal;
font-family: inherit;
}
button::after {
border: none;
}
.mine-top-panel{
width: 100vw;
height: 500rpx;
background-color: #beecd8;
border-bottom-left-radius: 50% 50rpx;
border-bottom-right-radius: 50% 50rpx;
overflow: hidden;
.user-info{
padding-left: 40rpx;
image {
width: 150rpx;
height: 150rpx;
border-radius: 50%;
}
.user-logged-in{
display: flex;
align-items: center;
.user-logged-in-info{
padding-left: 20rpx;
display: flex;
flex-direction: column;
.nickname{
color: #1a1a1a;
font-weight: 800;
}
.phone{
color: #000;
}
}
}
.user-not-logged-in{
display: flex;
align-items: center;
.login-button{
padding-left: 20rpx;
}
}
}
}
.mine-middle-panel{
width: 90vw;
height: 200rpx;
background-color: #fff;
margin-top: -100rpx;
border-radius: 20rpx; /* 四角小圆角 */
box-shadow: 0 8rpx 16rpx rgba(0, 0, 0, 0.05); /* 柔和阴影 */
display: flex;
justify-content: space-between;
padding-left: 20rpx;
padding-right: 20rpx;
.mine-info-panel{
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 23%;
}
}
}
/* 弹窗样式 */
.popup-container {
background-color: #fff;
padding: 40rpx 30rpx 60rpx;
border-top-left-radius: 30rpx;
border-top-right-radius: 30rpx;
.popup-header {
text-align: center;
margin-bottom: 30rpx;
.popup-title {
font-size: 36rpx;
font-weight: bold;
}
}
.avatar-nickname {
display: flex;
flex-direction: column;
align-items: center;
margin-bottom: 30rpx;
.avatar-selector {
width: 145rpx;
height: 145rpx;
border-radius: 50%;
font-size: 26rpx;
display: flex;
align-items: center;
justify-content: center;
margin-bottom: 20rpx;
background-color: #eee;
}
.avatar-preview {
width: 100%;
height: 100%;
border-radius: 50%;
}
.nickname-input {
width: 80%;
border: 1rpx solid #ccc;
border-radius: 20rpx;
padding: 20rpx;
font-size: 26rpx;
text-align: center;
}
}
.confirm-btn {
background-color: #07c160;
color: white;
font-size: 30rpx;
border-radius: 50rpx;
padding: 20rpx 0;
width: 100%;
}
}
</style>