feat(frontend): make growth assignments selectable

This commit is contained in:
2026-07-10 00:04:39 +08:00
parent 6b8ccd5a35
commit baf27a5de9
2 changed files with 38 additions and 8 deletions
+36 -6
View File
@@ -107,6 +107,12 @@
<h2>待训任务</h2>
<el-button type="danger" plain @click="createManualAssignment">派发专项</el-button>
</div>
<div class="assignment-form">
<el-select v-model="assignmentScenarioId" filterable placeholder="选择专项场景">
<el-option v-for="scenario in scenarios" :key="scenario.id" :label="scenario.name" :value="scenario.id" />
</el-select>
<el-input v-model="assignmentReason" placeholder="派发原因" />
</div>
<el-table :data="assignments" size="small">
<el-table-column prop="traineeName" label="学员" width="110" />
<el-table-column prop="scenarioName" label="训练" min-width="160" />
@@ -136,7 +142,7 @@ import { Download, Refresh } from '@element-plus/icons-vue';
import { ElMessage } from 'element-plus';
import FileSaver from 'file-saver';
import { computed, onMounted, ref, watch } from 'vue';
import { listPracticeScenarios } from '@/api/aihr/practice';
import { listPracticeScenarios, type PracticeScenarioResponse } from '@/api/aihr/practice';
import {
createPracticeAssignment,
getCompetencyProfile,
@@ -160,6 +166,9 @@ const evidence = ref<PromotionEvidence | null>(null);
const alerts = ref<PracticeAlert[]>([]);
const assignments = ref<PracticeAssignment[]>([]);
const orgSnapshot = ref<OrgSnapshotResponse | null>(null);
const scenarios = ref<PracticeScenarioResponse[]>([]);
const assignmentScenarioId = ref('');
const assignmentReason = ref('HR在成长激励页派发专项训练');
const rules = [
{ source: '训练完成', points: '+5', guard: '只认完成记录,不按点击或打开计分' },
@@ -206,22 +215,34 @@ const loadAll = async () => {
}
};
const loadScenarios = async () => {
try {
scenarios.value = ((await listPracticeScenarios()).data || []).filter((item) => item.enabled);
assignmentScenarioId.value = assignmentScenarioId.value || scenarios.value[0]?.id || '';
} catch (error) {
scenarios.value = [];
}
};
const createManualAssignment = async () => {
const party = extPartyId.value.trim() || evidence.value?.extPartyId || '';
if (!party) {
ElMessage.warning('请先输入员工手机号或 extPartyId');
return;
}
const scenario = scenarios.value.find((item) => item.id === assignmentScenarioId.value);
if (!scenario) {
ElMessage.warning('请先选择专项场景');
return;
}
try {
const scenarios = (await listPracticeScenarios()).data || [];
const scenario = scenarios.find((item) => item.enabled) || scenarios[0];
await createPracticeAssignment({
extPartyId: party,
traineeName: selectedPerson.value?.personName || party,
scenarioId: scenario?.id || 'fee-parking',
scenarioName: scenario?.name,
scenarioId: scenario.id,
scenarioName: scenario.name,
source: 'manual',
reason: 'HR在成长激励页派发专项训练'
reason: assignmentReason.value.trim() || 'HR在成长激励页派发专项训练'
});
ElMessage.success('专项训练已派发');
await loadAll();
@@ -279,6 +300,7 @@ watch(extPartyId, () => {
onMounted(() => {
loadOrgSnapshot();
loadScenarios();
loadAll();
});
</script>
@@ -374,6 +396,13 @@ onMounted(() => {
}
}
.assignment-form {
display: grid;
grid-template-columns: minmax(180px, 0.75fr) minmax(220px, 1fr);
gap: 10px;
margin-bottom: 12px;
}
.dimension-list,
.stage-list,
.alert-list {
@@ -431,6 +460,7 @@ onMounted(() => {
@media (max-width: 1080px) {
.page-head,
.main-grid,
.assignment-form,
.metric-grid {
grid-template-columns: 1fr;
}