158 lines
3.6 KiB
Vue
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>
|