852 lines
20 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="page-content">
<view v-if="userStatus === 'verified'" class="user-box flex" :style="{'padding-top': statusBaeHeight + 60 + 'px'}" @click="toSettings">
<image v-if="userInfo.avatar" :src="userInfo.avatar" class="avatar-img"></image>
<image v-else-if="barInfo.barLogo" :src="barInfo.barLogo" class="avatar-img"></image>
<view v-else class="avatar-placeholder flex align-center justify-center">
<text class="cuIcon-people text-xl"></text>
</view>
<view class="flex-direction flex">
<text class="text-xl font-bold margin-bottom">{{ userInfo.nickName || barInfo.nickName || '未设置昵称' }}</text>
<text class="text-sm margin-bottom-sm text-gray">门店名称{{ barInfo.barName || '-'}}</text>
<view class="flex align-center margin-bottom-sm">
<text class="text-sm text-gray">门店ID{{ barInfo.barNumber || '-' }}</text>
<view class="copy-btn" @click.stop="copyBarNumber">
<text class="cuIcon-copy"></text>
</view>
</view>
<view v-if="barInfo" class="auth-status">
<text v-if="barInfo.authState == 0" class="status-tag">未认证</text>
<text v-else-if="barInfo.authState == 2" class="status-tag">认证中</text>
<text v-else class="status-tag">{{ barInfo.authEndTime }}认证到期</text>
</view>
</view>
</view>
<view v-else class="user-box flex align-center justify-start" :style="{'padding-top': statusBaeHeight + 60 + 'px'}" @click="handleUserBoxClick">
<view class="avatar-placeholder flex align-center justify-center">
<image src="/static/default-avatar.svg" class="default-avatar"></image>
</view>
<view class="login-text flex align-center">
<view class="flex-col status-text">
<block v-if="userStatus === 'guest'">
<text class="text-xl font-bold">登录/认证</text>
</block>
<block v-else-if="userStatus === 'unverified'">
<text class="text-xl font-bold">请点击认证门店信息</text>
</block>
<block v-else-if="userStatus === 'verifying'">
<text class="text-xl font-bold">正在认证审核中</text>
<text class="text-xs text-gray">请耐心等待</text>
</block>
</view>
<text class="cuIcon-right text-gray"></text>
</view>
</view>
<view v-if="barInfo" class="scan-box">
<text>本月累计扫码酒款数量</text>
<view class="margin-top">
<view class="flex justify-between align-end margin-bottom-xs">
<text class="text-xxl text-bold">{{myScanData.scanCount}}</text>
<text class="text-xs">击败全国{{myScanData.percent}}%认证门店</text>
</view>
<view class="cu-progress round striped active">
<view class="bg-green" :style="[{ width:`${myScanData.percent}%`}]"></view>
</view>
</view>
</view>
<!-- 功能区 -->
<view class="fun-box">
<view class="flex justify-between align-center margin-bottom" @click="toPage(1)">
<view class="flex align-center">
<image src="@/static/mine.svg" class="icon"></image>
<text class="text-lg">我参与的</text>
</view>
<text class="cuIcon-right"></text>
</view>
<view class="flex justify-between align-center margin-bottom" @click="toPage(2)">
<view class="flex align-center">
<image src="@/static/focus on.svg" class="icon"></image>
<text class="text-lg">我的关注</text>
</view>
<text class="cuIcon-right"></text>
</view>
<view class="flex justify-between align-center margin-bottom" @click="toPage(3)">
<view class="flex align-center">
<image src="@/static/Wine Review.svg" class="icon"></image>
<text class="text-lg">我的酒评</text>
</view>
<text class="cuIcon-right"></text>
</view>
<view class="flex justify-between align-center margin-bottom" @click="toPage(5)">
<view class="flex align-center">
<image src="@/static/help.svg" class="icon"></image>
<text class="text-lg">添加啤啤猩球小助手</text>
</view>
<text class="cuIcon-right"></text>
</view>
</view>
<view class="fun-box">
<view class="flex justify-between align-center margin-bottom" @click="toPage(6)">
<view class="flex align-center">
<image src="@/static/Opinion.svg" class="icon"></image>
<text class="text-lg">意见反馈</text>
</view>
<text class="cuIcon-right"></text>
</view>
<view class="flex justify-between align-center margin-bottom" @click="toPage(4)">
<view class="flex align-center">
<image src="@/static/map.svg" class="icon"></image>
<text class="text-lg">地址信息</text>
</view>
<text class="cuIcon-right"></text>
</view>
<view class="flex justify-between align-center margin-bottom" @click="toPage(7)">
<view class="flex align-center">
<image src="@/static/set up.svg" class="icon"></image>
<text class="text-lg">设置</text>
</view>
<text class="cuIcon-right"></text>
</view>
</view>
<view v-if="userInfo" class="flex justify-center">
<button class="cu-btn btn" style="background-color: #dedede;" @click="logout">退出登录</button>
</view>
<loginPopup ref="loginRef" @loginSuccess="loginSuccess"></loginPopup>
</view>
</template>
<script>
import {
getBarInfo
} from '@/api/bar.js'
import { getMyScanData } from '@/api/user.js'
import loginPopup from '@/components/loginPopup.vue';
import { getToken, removeToken, getUserInfo as getUserInfoFromAuth, checkLogin, clearLoginStatus } from '@/utils/auth.js';
export default {
components: {
loginPopup
},
data() {
return {
userInfo: null,
loading: true,
barInfo: null,
myScanData: null,
statusBaeHeight: 40,
isLoggedIn: false
};
},
computed: {
// 用户状态
userStatus() {
console.log('登录状态检查:', {
isLoggedIn: this.isLoggedIn,
barInfo: this.barInfo,
authState: this.barInfo ? this.barInfo.authState : 'barInfo为空'
});
if (!this.isLoggedIn) return 'guest';
if (!this.barInfo || this.barInfo.authState === 0) return 'unverified';
if (this.barInfo.authState === 2) return 'verifying';
return 'verified';
},
maskedPhone() {
if (!this.barInfo || !this.barInfo.barContactPhone) return '';
return this.barInfo.barContactPhone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2');
}
},
onLoad() {
this.statusBaeHeight = uni.getWindowInfo.statusBarHeight
},
onShow() {
console.log('页面显示,检查登录状态');
this.checkLoginStatus();
},
methods: {
// 检查登录状态
async checkLoginStatus() {
try {
const token = uni.getStorageSync('token');
const userInfo = uni.getStorageSync('userInfo');
// 检查token和userInfo是否有效
if (!token || token.startsWith('temp_') || !userInfo) {
this.isLoggedIn = false;
this.userInfo = null;
this.barInfo = null;
this.myScanData = null;
return false;
}
this.isLoggedIn = true;
this.userInfo = userInfo;
// 先获取酒吧信息
await getBarInfo().then(res => {
if (res && res.data) {
this.barInfo = res.data;
// 如果是认证中状态,设置默认的扫码数据
if (this.barInfo.authState === 2) {
this.myScanData = { scanCount: 0, percent: 0 };
}
}
}).catch(err => {
console.error('获取酒吧信息失败:', err);
if (err.code === 500 && err.msg.includes('门店未认证')) {
this.barInfo = {
authState: 2,
barName: '',
barNumber: '',
barContactPhone: ''
};
this.myScanData = { scanCount: 0, percent: 0 };
} else {
this.barInfo = null;
}
});
// 如果不是认证中状态,获取扫码数据
if (this.barInfo && this.barInfo.authState !== 2) {
await getMyScanData().then(res => {
if (res.code === 200) {
this.myScanData = res.data;
}
}).catch(err => {
console.error('获取扫码数据失败:', err);
this.myScanData = { scanCount: 0, percent: 0 };
});
}
return true;
} catch (error) {
console.error('检查登录状态失败:', error);
return false;
} finally {
this.loading = false;
}
},
loginSuccess() {
console.log('登录成功,开始更新页面数据');
// 更新登录状态
this.userInfo = getUserInfoFromAuth();
this.isLoggedIn = true;
// 使用 Promise.all 同时获取所有需要的数据
Promise.all([
this.getBarInfoFun(),
this.getMyScanDataFun()
]).then(() => {
console.log('所有数据更新完成');
// 强制更新视图
this.$forceUpdate();
// 显示登录成功提示
uni.showToast({
title: '登录成功',
icon: 'success',
duration: 1500
});
}).catch(err => {
console.error('数据更新失败:', err);
uni.showToast({
title: '数据更新失败',
icon: 'none'
});
});
},
// 获取酒吧信息
getBarInfoFun() {
if (!this.isLoggedIn) {
console.log('用户未登录,不获取酒吧信息');
return Promise.reject('未登录');
}
return getBarInfo().then(res => {
console.log('获取酒吧信息成功:', res);
if (res && res.data) {
this.barInfo = res.data;
// 强制更新视图
this.$forceUpdate();
return this.barInfo;
} else {
console.log('获取酒吧信息成功,但数据为空');
this.barInfo = null;
return Promise.reject('数据为空');
}
}).catch(err => {
console.error('获取酒吧信息失败:', err);
this.barInfo = null;
return Promise.reject(err);
});
},
// 获取我的扫码数据
getMyScanDataFun() {
if (!this.isLoggedIn) {
return Promise.reject('未登录');
}
return getMyScanData().then(res => {
if (res.code === 200) {
this.myScanData = res.data;
return this.myScanData;
} else {
return Promise.reject(res);
}
}).catch(err => {
console.error('获取扫码数据失败:', err);
uni.showToast({
title: '获取扫码数据失败',
icon: 'none'
});
return Promise.reject(err);
});
},
// 处理用户信息区域点击
handleUserBoxClick() {
switch (this.userStatus) {
case 'guest':
this.$refs.loginRef.open();
break;
case 'unverified':
uni.navigateTo({
url: '/pages/index/registration'
});
break;
case 'verifying':
uni.showToast({
title: '您的门店正在认证中,请耐心等待',
icon: 'none'
});
break;
default:
break;
}
},
// 页面跳转
toPage(index) {
// 添加枝点小助手不需要登录
if (index === 5) {
uni.navigateTo({
url: '/pagesMy/addAiad'
});
return;
}
// 检查登录状态
if (!this.isLoggedIn) {
this.$refs.loginRef.open();
return;
}
// 检查认证状态
if (this.userStatus === 'unverified') {
uni.navigateTo({
url: '/pages/index/registration'
});
return;
}
// 认证中状态只能查看部分功能
if (this.userStatus === 'verifying') {
if (index === 6) { // 意见反馈
uni.navigateTo({
url: '/pagesMy/feedback'
});
return;
}
uni.showToast({
title: '您的门店正在认证中,请耐心等待',
icon: 'none'
});
return;
}
// 已认证状态可以访问所有功能
switch (index) {
case 1: // 我参与的
uni.switchTab({
url: '/pages/index/myJoin'
});
break;
case 2: // 我的关注
uni.navigateTo({
url: '/pagesMy/myAttention'
});
break;
case 3: // 我的酒评
uni.navigateTo({
url: '/pagesMy/myWineReview'
});
break;
case 4: // 我的地址
uni.navigateTo({
url: '/pagesMy/myAddress'
});
break;
case 6: // 意见反馈
uni.navigateTo({
url: '/pagesMy/feedback'
});
break;
case 7: // 设置
uni.navigateTo({
url: '/pagesMy/setting'
});
break;
default:
break;
}
},
// 退出登录
logout() {
uni.showModal({
title: '提示',
content: '确定要退出登录吗?',
success: (res) => {
if (res.confirm) {
// 清除本地存储的用户信息
clearLoginStatus();
// 跳转到首页
uni.reLaunch({
url: '/pages/index/index'
});
}
}
});
},
// 关闭登录弹窗
closeLoginPopup() {
this.$refs.loginRef.close();
},
// 去登录
toLogin() {
uni.navigateTo({
url: '/pages/index/registration'
});
},
// 跳转到设置页面
toSettings() {
if (this.userStatus === 'verified') {
uni.navigateTo({
url: '/pagesMy/setting'
})
}
},
// 显示修改头像提示
showChangeAvatar() {
uni.showActionSheet({
itemList: ['修改头像'],
success: () => {
this.toSettings();
}
});
},
// 跳转到设置页面(统一使用这个方法)
toSetting() {
if (this.userStatus === 'verified') {
uni.navigateTo({
url: '/pagesMy/setting'
});
}
},
// 获取用户信息
async getUserInfo() {
try {
if (!this.isLoggedIn) {
console.log('未登录状态');
return;
}
const result = await getUserInfoFromAuth();
console.log('获取用户信息结果:', result);
if (result && result.barId) {
this.barInfo = result;
// 如果用户没有昵称,设置默认昵称
if (!this.barInfo.nickName) {
this.barInfo.nickName = this.barInfo.barName + '01';
}
} else {
console.error('获取用户信息失败:', result);
// 不重置登录状态,只显示错误提示
uni.showToast({
title: '获取用户信息失败',
icon: 'none'
});
}
} catch (error) {
console.error('获取用户信息出错:', error);
uni.showToast({
title: '获取用户信息失败',
icon: 'none'
});
}
},
// 复制门店ID
copyBarNumber() {
if (!this.barInfo || !this.barInfo.barNumber) {
uni.showToast({
title: '暂无门店ID',
icon: 'none'
});
return;
}
uni.setClipboardData({
data: this.barInfo.barNumber,
success: () => {
uni.showToast({
title: '复制成功',
icon: 'success'
});
}
});
},
// 选择头像
async onChooseAvatar() {
try {
// 调用微信选择头像接口
const res = await uni.chooseImage({
count: 1,
sizeType: ['compressed'],
sourceType: ['album', 'camera']
});
if (res.tempFilePaths && res.tempFilePaths.length > 0) {
uni.showLoading({
title: '上传中...'
});
// 上传头像
const uploadRes = await uni.uploadFile({
url: '/bar/barinfo', // 使用编辑酒吧信息接口
filePath: res.tempFilePaths[0],
name: 'barLogo', // 修改为正确的参数名
header: {
'Authorization': getToken()
},
formData: {
// 添加其他必要的参数
barNumber: this.barInfo.barNumber
}
});
// 解析响应数据
let result;
try {
result = JSON.parse(uploadRes.data);
} catch (e) {
result = uploadRes.data;
}
if (result.code === 200 && result.data) {
// 更新本地存储的门店信息
const barInfo = uni.getStorageSync('barInfo');
barInfo.barLogo = result.data;
uni.setStorageSync('barInfo', barInfo);
// 更新页面显示
this.barInfo = barInfo;
uni.showToast({
title: '更新成功',
icon: 'success'
});
} else {
throw new Error(result.msg || '上传失败');
}
}
} catch (error) {
console.error('选择头像失败:', error);
uni.showToast({
title: error.message || '选择头像失败',
icon: 'none'
});
} finally {
uni.hideLoading();
}
}
}
}
</script>
<style lang="scss" scoped>
.page-content {
min-height: 100vh;
background: #F8F8F8;
padding-bottom: env(safe-area-inset-bottom);
}
.user-box {
background: #19367A ;
padding: 32rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 12rpx rgba(25, 54, 122, 0.2);
.flex-direction {
.text-xl {
color: #FFFFFF;
text-shadow: 0 2rpx 4rpx rgba(0, 0, 0, 0.1);
font-size: 36rpx;
margin-bottom: 16rpx;
line-height: 1.2;
}
.text-sm {
color: rgba(255, 255, 255, 0.9);
font-size: 26rpx;
margin-bottom: 12rpx;
line-height: 1.2;
&.margin-bottom-sm {
margin-bottom: 12rpx;
}
&.text-gray {
color: rgba(255, 255, 255, 0.9);
}
}
}
.avatar-img, .avatar-placeholder {
width: 140rpx;
height: 140rpx;
border-radius: 70rpx;
margin-right: 32rpx;
flex-shrink: 0;
}
.avatar-img {
border: 4rpx solid rgba(255, 255, 255, 0.8);
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.1);
}
.avatar-placeholder {
background: rgba(255, 255, 255, 0.2);
display: flex;
align-items: center;
justify-content: center;
.default-avatar {
width: 70rpx;
height: 70rpx;
}
.cuIcon-people {
font-size: 70rpx;
color: rgba(255, 255, 255, 0.8);
}
}
.login-text {
height: auto;
.status-text {
margin-right: 16rpx;
text {
display: block;
color: #FFFFFF;
&.text-xl {
font-size: 36rpx;
margin-bottom: 12rpx;
line-height: 1.2;
font-weight: bold;
}
&.text-xs {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
line-height: 1.2;
}
}
}
.cuIcon-right {
color: rgba(255, 255, 255, 0.8);
font-size: 28rpx;
}
}
.auth-status {
margin-top: 4rpx;
.status-tag {
display: inline-block;
padding: 4rpx 16rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 20rpx;
font-size: 24rpx;
color: #FFFFFF;
}
}
.copy-btn {
margin-left: 32rpx;
padding: 6rpx 16rpx;
background: rgba(255, 255, 255, 0.2);
border-radius: 20rpx;
.cuIcon-copy {
color: #FFFFFF;
font-size: 24rpx;
}
}
}
.scan-box {
background: #FFFFFF;
margin: 0 24rpx 32rpx;
padding: 32rpx;
border-radius: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
text {
color: #666666;
font-size: 28rpx;
}
.margin-top {
margin-top: 24rpx;
}
.text-xxl {
font-size: 48rpx;
color: #333333;
font-weight: 600;
line-height: 1.2;
}
.text-xs {
color: #666666;
font-size: 24rpx;
}
.cu-progress {
height: 12rpx;
background: #F5F5F5;
margin-top: 16rpx;
border-radius: 8rpx;
overflow: hidden;
.bg-green {
background: linear-gradient(90deg, #19367A 0%, #2C4B9E 100%);
transition: width 0.3s ease;
}
}
}
.fun-box {
background: #FFFFFF;
margin: 0 24rpx 24rpx;
padding: 32rpx;
border-radius: 16rpx;
box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);
.margin-bottom {
width: 630rpx;
height: 80rpx;
display: flex;
align-items: center;
justify-content: space-between;
position: relative;
margin: 0 auto;
&:not(:last-child) {
margin-bottom: 24rpx;
}
&:active {
opacity: 0.7;
}
.flex.align-center {
height: 100%;
display: flex;
align-items: center;
.icon {
width: 96rpx;
height: 96rpx;
margin-right: 24rpx;
opacity: 0.9;
flex-shrink: 0;
}
.text-lg {
color: #333333;
font-size: 30rpx;
font-weight: 400;
letter-spacing: 0.5rpx;
line-height: 1;
}
}
.cuIcon-right {
color: #CCCCCC;
font-size: 24rpx;
height: 100%;
display: flex;
align-items: center;
transition: transform 0.3s ease;
}
&:active .cuIcon-right {
transform: translateX(4rpx);
}
}
// 分组样式
& + .fun-box {
margin-top: 24rpx;
}
}
.cu-btn {
width: calc(100% - 48rpx);
height: 88rpx;
line-height: 88rpx;
border-radius: 44rpx;
font-size: 30rpx;
margin: 24rpx auto 0;
background: #F5F5F5;
color: #666666;
transition: all 0.3s ease;
letter-spacing: 1rpx;
&:active {
opacity: 0.8;
transform: scale(0.98);
background: #EBEBEB;
}
}
.login-text {
height: 160rpx;
transition: opacity 0.3s ease;
.status-text {
margin-right: 16rpx;
text {
display: block;
&.text-xl {
font-size: 36rpx;
margin-bottom: 12rpx;
}
&.text-xs {
font-size: 24rpx;
color: rgba(255, 255, 255, 0.8);
}
}
}
}
</style>