feat(aihr): filter supervisor reviews by org scope

This commit is contained in:
2026-07-09 12:43:16 +08:00
parent 45d06f56cd
commit 9bd567a72f
8 changed files with 281 additions and 40 deletions
+50 -5
View File
@@ -6,7 +6,17 @@
<p>展示能力画像、初/中/高级证据包、预警、待训任务和学分规则最小集。</p>
</div>
<div class="head-actions">
<el-input v-model="extPartyId" clearable placeholder="员工手机号或 extPartyId" />
<el-select v-model="selectedProjectCode" clearable filterable placeholder="项目范围">
<el-option v-for="item in orgSnapshot?.projects || []" :key="item.projectCode" :label="item.projectName" :value="item.projectCode" />
</el-select>
<el-select v-model="extPartyId" clearable filterable allow-create default-first-option placeholder="组织人员或 extPartyId">
<el-option
v-for="person in orgPeople"
:key="person.extPartyId"
:label="`${person.personName} / ${person.positionName}`"
:value="person.extPartyId"
/>
</el-select>
<el-button type="danger" :icon="Refresh" :loading="loading" @click="loadAll">刷新</el-button>
</div>
</section>
@@ -123,27 +133,31 @@
<script setup name="CompetencyGrowth" lang="ts">
import { Refresh } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import { onMounted, ref } from 'vue';
import { computed, onMounted, ref, watch } from 'vue';
import { listPracticeScenarios } from '@/api/aihr/practice';
import {
createPracticeAssignment,
getCompetencyProfile,
getOrgSnapshot,
getPromotionEvidence,
listPracticeAlerts,
listPracticeAssignments,
type CompetencyProfile,
type OrgSnapshotResponse,
type PracticeAlert,
type PracticeAssignment,
type PromotionEvidence
} from '@/api/aihr/mobile-admin';
const extPartyId = ref('');
const selectedProjectCode = ref('');
const loading = ref(false);
const leaderboardEnabled = ref(false);
const profile = ref<CompetencyProfile | null>(null);
const evidence = ref<PromotionEvidence | null>(null);
const alerts = ref<PracticeAlert[]>([]);
const assignments = ref<PracticeAssignment[]>([]);
const orgSnapshot = ref<OrgSnapshotResponse | null>(null);
const rules = [
{ source: '训练完成', points: '+5', guard: '只认完成记录,不按点击或打开计分' },
@@ -152,6 +166,23 @@ const rules = [
{ source: '课程考试通过', points: '+10', guard: '阶段二课程考试上线后启用' }
];
const orgPeople = computed(() => orgSnapshot.value?.rows || []);
const selectedPerson = computed(() => orgPeople.value.find((item) => item.extPartyId === extPartyId.value));
const loadOrgSnapshot = async () => {
try {
const result = await getOrgSnapshot({
status: 'active',
projectCode: selectedProjectCode.value,
pageNum: 1,
pageSize: 500
});
orgSnapshot.value = result.data;
} catch (error) {
orgSnapshot.value = null;
}
};
const loadAll = async () => {
loading.value = true;
const party = extPartyId.value.trim();
@@ -184,7 +215,7 @@ const createManualAssignment = async () => {
const scenario = scenarios.find((item) => item.enabled) || scenarios[0];
await createPracticeAssignment({
extPartyId: party,
traineeName: party,
traineeName: selectedPerson.value?.personName || party,
scenarioId: scenario?.id || 'fee-parking',
scenarioName: scenario?.name,
source: 'manual',
@@ -197,7 +228,19 @@ const createManualAssignment = async () => {
}
};
onMounted(loadAll);
watch(selectedProjectCode, async () => {
extPartyId.value = '';
await loadOrgSnapshot();
});
watch(extPartyId, () => {
loadAll();
});
onMounted(() => {
loadOrgSnapshot();
loadAll();
});
</script>
<style scoped lang="scss">
@@ -236,7 +279,7 @@ onMounted(loadAll);
.head-actions {
display: grid;
grid-template-columns: 260px auto;
grid-template-columns: 220px 280px auto;
gap: 10px;
}
@@ -357,6 +400,8 @@ onMounted(loadAll);
}
.head-actions {
display: grid;
grid-template-columns: 1fr;
margin-top: 14px;
}
}