Files
prop-ai-hr/mobile-uni/src/pages/auth/position/index.vue
T

158 lines
3.6 KiB
Vue

<template>
<view class="page position-page">
<view class="position-head">
<text class="page-title">确认岗位</text>
<text class="page-subtitle">{{ phone }}</text>
</view>
<view v-if="message" class="status-message">{{ message }}</view>
<view class="panel">
<text class="panel-title">选择当前岗位</text>
<view class="position-list">
<button
v-for="item in positionCards"
:key="item.value"
class="position-card"
:class="{ active: item.value === selectedPosition }"
:disabled="saving"
@click="selectPosition(item.value)"
>
<view class="position-copy">
<text class="position-name">{{ item.value }}</text>
<text class="position-title">{{ item.heroTitle }}</text>
</view>
<text class="position-mark">{{ item.value === selectedPosition ? '已选' : '选择' }}</text>
</button>
</view>
</view>
</view>
</template>
<script setup lang="ts">
import { computed, ref } from 'vue';
import { onLoad, onShow } from '@dcloudio/uni-app';
import {
getAuth,
getPositionProfile,
isLoggedIn,
rememberLoginRedirect,
saveSelectedPosition,
userPositionOptions,
type UserPosition
} from '@/services/auth';
import { goToMobileTarget, hydratePositionFromOrg } from '@/services/position';
import { resetPageScroll } from '@/services/navigation';
const redirect = ref('/pages/user/today/index');
const selectedPosition = ref<UserPosition | ''>('');
const saving = ref(false);
const message = ref('');
const phone = computed(() => getAuth().phone || '未登录');
const positionCards = userPositionOptions.map((item) => getPositionProfile(item));
const finish = () => {
goToMobileTarget(redirect.value || '/pages/user/today/index');
};
const selectPosition = (position: UserPosition) => {
if (saving.value) return;
saving.value = true;
const saved = saveSelectedPosition(position);
selectedPosition.value = saved;
finish();
};
const autoFillFromOrg = async () => {
if (!isLoggedIn()) {
rememberLoginRedirect(redirect.value);
uni.redirectTo({ url: '/pages/auth/login/index' });
return;
}
const officialPosition = await hydratePositionFromOrg();
if (officialPosition) {
selectedPosition.value = officialPosition;
finish();
return;
}
message.value = '未从组织数据匹配到岗位,请确认当前岗位';
};
onLoad((query) => {
if (typeof query?.redirect === 'string') {
const target = decodeURIComponent(query.redirect);
if (target.startsWith('/pages/')) {
redirect.value = target;
}
}
});
onShow(() => {
resetPageScroll();
void autoFillFromOrg();
});
</script>
<style scoped>
.position-page {
display: flex;
min-height: 100vh;
flex-direction: column;
justify-content: center;
}
.position-head {
margin-bottom: 10px;
}
.position-list {
display: flex;
margin-top: 16px;
flex-direction: column;
gap: 10px;
}
.position-card {
display: flex;
min-height: 72px;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 14px 16px;
border: 1px solid #e2e8f0;
border-radius: 16px;
background: #f8fafc;
text-align: left;
}
.position-card.active {
border-color: #2563eb;
background: #eff6ff;
}
.position-copy {
display: flex;
min-width: 0;
flex-direction: column;
}
.position-name {
color: #0f172a;
font-size: 18px;
font-weight: 900;
}
.position-title {
margin-top: 6px;
color: #64748b;
font-size: 13px;
}
.position-mark {
color: #2563eb;
font-size: 14px;
font-weight: 900;
white-space: nowrap;
}
</style>