fix(mobile): require employee position before user flow

This commit is contained in:
2026-07-09 17:09:26 +08:00
parent 8b92a7e9ac
commit 8f73cb0c84
13 changed files with 473 additions and 33 deletions
+88 -1
View File
@@ -14,6 +14,26 @@
<button v-else class="secondary-button account-action" @click="logout">退出</button>
</view>
<view v-if="loggedIn" class="panel position-panel">
<view class="position-current">
<view>
<text class="panel-title">岗位身份</text>
<text class="position-title">{{ positionProfile.value }} · {{ positionProfile.heroTitle }}</text>
</view>
</view>
<view class="position-actions">
<button
v-for="item in positionCards"
:key="item.value"
class="position-chip"
:class="{ active: item.value === positionProfile.value }"
@click="changePosition(item.value)"
>
{{ item.value }}
</button>
</view>
</view>
<view v-if="profile" class="panel">
<text class="panel-title">成长摘要</text>
<view class="score-row">
@@ -117,9 +137,20 @@
import { ref } from 'vue';
import { onShow } from '@dcloudio/uni-app';
import type { CompetencyProfile, PracticeRecord, PromotionEvidence } from '@/types/api';
import { clearAuth, getAuth, isLoggedIn, rememberLoginRedirect } from '@/services/auth';
import {
clearAuth,
getAuth,
getPositionProfile,
getSelectedPositionProfile,
isLoggedIn,
rememberLoginRedirect,
saveSelectedPosition,
userPositionOptions,
type UserPosition
} from '@/services/auth';
import { getCompetencyProfile, getPracticeHistory, getPromotionEvidence } from '@/services/practice';
import { resetPageScroll } from '@/services/navigation';
import { ensureEmployeePosition } from '@/services/position';
const loggedIn = ref(false);
const phone = ref('');
@@ -128,11 +159,14 @@ const message = ref('');
const profile = ref<CompetencyProfile | null>(null);
const history = ref<PracticeRecord[]>([]);
const evidence = ref<PromotionEvidence | null>(null);
const positionProfile = ref(getSelectedPositionProfile());
const positionCards = userPositionOptions.map((item) => getPositionProfile(item));
const refreshAuth = () => {
const auth = getAuth();
loggedIn.value = isLoggedIn();
phone.value = auth.phone;
positionProfile.value = getSelectedPositionProfile();
};
const clearProfileData = () => {
@@ -147,6 +181,10 @@ const loadData = async () => {
clearProfileData();
return;
}
if (!(await ensureEmployeePosition('/pages/user/profile/index'))) {
return;
}
refreshAuth();
loading.value = true;
message.value = '';
try {
@@ -183,6 +221,13 @@ const logout = () => {
uni.showToast({ title: '已退出', icon: 'none' });
};
const changePosition = (position: UserPosition) => {
const saved = saveSelectedPosition(position);
if (!saved) return;
positionProfile.value = getSelectedPositionProfile();
uni.showToast({ title: '岗位已更新', icon: 'none' });
};
onShow(() => {
resetPageScroll();
void loadData();
@@ -214,6 +259,48 @@ onShow(() => {
min-width: 84px;
}
.position-current {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
}
.position-title {
display: block;
margin-top: 8px;
color: #2563eb;
font-size: 16px;
font-weight: 900;
}
.position-actions {
display: grid;
margin-top: 14px;
grid-template-columns: repeat(5, minmax(0, 1fr));
gap: 8px;
}
.position-chip {
display: flex;
min-height: 38px;
align-items: center;
justify-content: center;
border: 1px solid #e2e8f0;
border-radius: 12px;
background: #f8fafc;
color: #475569;
font-size: 13px;
font-weight: 900;
white-space: nowrap;
}
.position-chip.active {
border-color: #2563eb;
background: #eff6ff;
color: #1d4ed8;
}
.score-row {
display: grid;
margin-top: 16px;