feat: restore learning feedback and knowledge capabilities

This commit is contained in:
2026-07-18 00:50:11 +08:00
parent 876a23a123
commit 6bdc86e3fc
152 changed files with 30337 additions and 953 deletions
+34 -87
View File
@@ -6,7 +6,7 @@
</view>
<view class="position-head">
<text class="page-title">确认岗位</text>
<text class="page-title">同步岗位</text>
<text class="page-subtitle">{{ phone }}</text>
</view>
@@ -16,27 +16,16 @@
</view>
<view class="panel">
<text class="panel-title">选择当前岗位</text>
<view class="position-grid">
<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>
<view class="position-radio" :class="{ checked: item.value === selectedPosition }" />
</button>
<text class="panel-title">岗位由人力系统统一维护</text>
<text class="position-help">员工端不支持手动切换岗位。系统会根据登录手机号匹配最新在职组织身份。</text>
<view v-if="selectedPosition" class="position-result">
<text class="position-name">{{ selectedPosition }}</text>
<text class="position-title">已匹配正式岗位</text>
</view>
</view>
<button class="confirm-button" :disabled="!selectedPosition || saving" @click="confirmPosition">
{{ saving ? '保存中…' : '确认岗位' }}
<button class="confirm-button" :disabled="saving" @click="autoFillFromOrg">
{{ saving ? '同步中…' : '重新同步岗位' }}
</button>
</view>
</template>
@@ -46,11 +35,8 @@ 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';
@@ -61,38 +47,31 @@ 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;
selectedPosition.value = position;
};
const confirmPosition = () => {
if (!selectedPosition.value || saving.value) return;
saving.value = true;
const saved = saveSelectedPosition(selectedPosition.value);
selectedPosition.value = saved;
finish();
};
const autoFillFromOrg = async () => {
if (saving.value) return;
if (!isLoggedIn()) {
rememberLoginRedirect(redirect.value);
uni.redirectTo({ url: '/pages/auth/login/index' });
return;
}
const officialPosition = await hydratePositionFromOrg();
if (officialPosition) {
selectedPosition.value = officialPosition;
finish();
return;
saving.value = true;
message.value = '';
try {
const officialPosition = await hydratePositionFromOrg();
if (officialPosition) {
selectedPosition.value = officialPosition;
finish();
return;
}
message.value = '人力系统中未匹配到当前手机号的在职岗位,请联系 HR 核对手机号、在职状态和岗位信息。';
} finally {
saving.value = false;
}
message.value = '未从组织数据匹配到岗位,可能是组织手机号未开放或已脱敏,请手动确认当前岗位';
};
onLoad((query) => {
@@ -186,37 +165,20 @@ onShow(() => {
font-weight: 800;
}
.position-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 12px;
.position-help {
display: block;
margin-top: 12px;
color: #7d8794;
font-size: 14px;
line-height: 1.65;
}
.position-result {
margin-top: 18px;
}
.position-card {
display: flex;
width: 100%;
box-sizing: border-box;
min-height: 112px;
align-items: center;
justify-content: space-between;
gap: 12px;
padding: 16px 14px;
border: 1px solid #e0e4e9;
border-radius: 16px;
background: #ffffff;
text-align: left;
}
.position-card.active {
border-color: #e70014;
background: #fffafa;
}
.position-copy {
display: flex;
min-width: 0;
flex-direction: column;
padding: 16px;
border: 1px solid #f2b9bf;
border-radius: 14px;
background: #fff7f8;
}
.position-name {
@@ -231,21 +193,6 @@ onShow(() => {
font-size: 13px;
}
.position-radio {
width: 22px;
height: 22px;
flex: none;
border: 2px solid #b8bec7;
border-radius: 50%;
box-sizing: border-box;
}
.position-radio.checked {
border-color: #e70014;
box-shadow: inset 0 0 0 5px #ffffff;
background: #e70014;
}
.confirm-button {
width: 100%;
min-height: 56px;