fix: login state refresh, hero layout, default avatar consistency

This commit is contained in:
yuzhiran
2026-06-15 11:04:00 +08:00
parent 07c6557454
commit 5a49d15696
3 changed files with 57 additions and 25 deletions
+5 -5
View File
@@ -24,8 +24,8 @@
### Step 4: 完整测试
```bash
# 构建检查
cd /root/opencode-workspace/zhiyin/backend && npx nest build 2>&1
# 构建检查(注意内存限制,服务器 OOM 时加 --max-old-space-size
cd /root/opencode-workspace/zhiyin/backend && NODE_OPTIONS="--max-old-space-size=2048" npx nest build 2>&1
# 单元测试
npm test -- --forceExit --detectOpenHandles 2>&1
@@ -43,14 +43,14 @@ npm test -- --forceExit --detectOpenHandles 2>&1
cd /root/opencode-workspace/zhiyin/backend && npx nest build
# 同步到生产目录
cp -rf dist/* /www/wwwroot/server/yzr-yhl/backend/dist/
cp -rf dist/* /www/wwwroot/server/zhiyin/backend/dist/
# 复制证书(postbuild 替代)
cp -r certs /www/wwwroot/server/yzr-yhl/backend/dist/src/certs
cp -r certs /www/wwwroot/server/zhiyin/backend/dist/src/certs
# 重启
pm2 restart yhl-backend
# 验证
sleep 3 && curl -s http://localhost:3002/api/share/visit/test?visitorId=v
sleep 3 && curl -s http://localhost:3006/api/user/wx-login -X POST -H "Content-Type: application/json" -d '{"code":"test"}'
```
+36 -7
View File
@@ -1,11 +1,14 @@
<template>
<view class="page fade-in">
<view class="hero">
<view class="hero-row">
<view class="hero-left">
<text class="hero-title">{{ greeting }}</text>
<text class="hero-sub">试试下面的功能开启你的求职练习</text>
</view>
<view class="hero-right">
<view class="user-card card" v-if="userInfo" @click="goProfile">
<image class="avatar" :src="userInfo.avatar || '/static/avatar-default.svg'" mode="aspectFill" />
<image class="avatar" :src="userInfo.avatar || '/static/avatar-default.png'" mode="aspectFill" />
<view class="user-meta">
<text class="user-name">{{ userInfo.nickname || '同学' }}</text>
<view class="user-tags">
@@ -15,6 +18,16 @@
</view>
<text class="arrow"></text>
</view>
<view class="guest-card card" v-else @click="goLogin">
<image class="avatar" src="/static/avatar-default.png" mode="aspectFill" />
<view class="user-meta">
<text class="user-name">立即登录</text>
<text class="guest-hint">登录后体验全部功能</text>
</view>
<text class="arrow"></text>
</view>
</view>
</view>
</view>
<!-- 功能入口 -->
@@ -129,6 +142,7 @@
<script setup>
import { ref, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { api } from '../../config'
const userInfo = ref(null)
@@ -139,8 +153,12 @@ const positionsLoading = ref(true)
const dailyQuestion = ref(null)
const showAnswer = ref(false)
const loadUserInfo = () => {
try { const s = uni.getStorageSync('userInfo'); if (s) userInfo.value = JSON.parse(s); else userInfo.value = null } catch (e) { userInfo.value = null }
}
onMounted(async () => {
try { const s = uni.getStorageSync('userInfo'); if (s) userInfo.value = JSON.parse(s) } catch (e) {}
loadUserInfo()
const h = new Date().getHours()
if (h < 6) greeting.value = '夜深了,早点休息 🌙'
else if (h < 12) greeting.value = '早上好 ☀️'
@@ -170,9 +188,12 @@ onMounted(async () => {
finally { positionsLoading.value = false }
})
onShow(loadUserInfo)
const refreshDaily = () => { showAnswer.value = false; /* trigger reload */ }
const goProfile = () => uni.switchTab({ url: '/pages/user/user' })
const goLogin = () => uni.navigateTo({ url: '/pages/login/login' })
const goInterview = () => uni.navigateTo({ url: '/pages/interview/interview' })
const goResume = () => uni.navigateTo({ url: '/pages/resume/resume' })
const goProgress = () => uni.navigateTo({ url: '/pages/progress/progress' })
@@ -190,16 +211,24 @@ const startInterview = (pos) => uni.navigateTo({ url: `/pages/interview/intervie
background: linear-gradient(135deg, var(--color-gradient-start) 0%, var(--color-gradient-mid) 50%, var(--color-gradient-end) 100%);
padding: 48rpx 32rpx 72rpx; border-radius: 0 0 48rpx 48rpx;
}
.hero-row { display: flex; align-items: flex-start; gap: 24rpx; }
.hero-left { flex: 1; min-width: 0; padding-top: 8rpx; }
.hero-right { flex-shrink: 0; width: 320rpx; }
.hero-title { font-size: 40rpx; font-weight: 700; color: #FFF; display: block; line-height: 1.3; }
.hero-sub { font-size: 22rpx; color: rgba(255,255,255,0.7); margin-top: 8rpx; display: block; }
.user-card {
.user-card, .guest-card {
background: rgba(255,255,255,0.95); backdrop-filter: blur(20rpx);
border-radius: var(--radius-xl); padding: 24rpx 28rpx;
display: flex; align-items: center; margin-top: 24rpx;
border-radius: var(--radius-xl); padding: 20rpx 24rpx;
display: flex; align-items: center;
box-shadow: 0 8rpx 32rpx rgba(0,0,0,0.1);
}
.avatar { width: 88rpx; height: 88rpx; border-radius: 50%; margin-right: 20rpx; border: 3rpx solid var(--color-primary-light); flex-shrink: 0; }
.guest-card { background: rgba(255,255,255,0.15); backdrop-filter: blur(10rpx); }
.guest-card .avatar { border-color: rgba(255,255,255,0.3); }
.guest-card .user-name { font-size: 26rpx; color: #FFF; }
.guest-hint { font-size: 20rpx; color: rgba(255,255,255,0.6); margin-top: 4rpx; display: block; }
.guest-card .arrow { color: rgba(255,255,255,0.4); }
.avatar { width: 72rpx; height: 72rpx; border-radius: 50%; margin-right: 16rpx; border: 3rpx solid var(--color-primary-light); flex-shrink: 0; }
.user-meta { flex: 1; min-width: 0; }
.user-name { font-size: 30rpx; font-weight: 600; color: var(--color-text); }
.user-tags { display: flex; gap: 10rpx; margin-top: 10rpx; }
+7 -4
View File
@@ -3,7 +3,7 @@
<!-- 个人中心 -->
<view class="header" v-if="isLoggedIn">
<view class="profile-section">
<image class="avatar" :src="userInfo.avatar || '/static/avatar-default.svg'" mode="aspectFill" />
<image class="avatar" :src="userInfo.avatar || '/static/avatar-default.png'" mode="aspectFill" />
<view class="profile-info">
<text class="nickname">{{ userInfo.nickname || '未设置昵称' }}</text>
<view class="plan-badge">{{ userInfo.plan || '免费版' }}</view>
@@ -33,7 +33,6 @@
<view class="guest-avatar"><text class="guest-icon">👤</text></view>
<view class="guest-info">
<text class="guest-name">未登录 / 点击登录</text>
<text class="guest-hint">登录后体验全部功能</text>
</view>
<text class="header-arrow"></text>
</view>
@@ -84,6 +83,7 @@
<script setup>
import { ref, computed, onMounted } from 'vue'
import { onShow } from '@dcloudio/uni-app'
import { api } from '../../config'
const userInfo = ref({})
@@ -93,13 +93,16 @@ const token = ref('')
const isLoggedIn = computed(() => !!token.value)
onMounted(() => {
const refreshState = () => {
token.value = uni.getStorageSync('token') || ''
if (!token.value) return
try { const s = uni.getStorageSync('userInfo'); if (s) userInfo.value = JSON.parse(s) } catch(e) {}
loadStats()
checkAdmin()
})
}
onMounted(refreshState)
onShow(refreshState)
const loadStats = async () => {
try {