<script lang="ts" setup>
|
import type { HrmPerformanceAppraiseApi } from '#/api/hrm/performance-appraise';
|
|
import { markRaw, ref } from 'vue';
|
|
import { useVbenModal } from '@vben/common-ui';
|
|
import { message } from 'ant-design-vue';
|
|
import {
|
getAppraiseItemList,
|
getAppraiseResult,
|
saveAppraiseResult,
|
} from '#/api/hrm/performance-appraise';
|
import { HrmEmployeeSelect } from '#/views/hrm/employee/components';
|
|
const emit = defineEmits(['success']);
|
|
const appraiseId = ref<number>();
|
const employeeId = ref<number>();
|
const items = ref<HrmPerformanceAppraiseApi.AppraiseItem[]>([]);
|
const comment = ref<string>('');
|
|
const SCORER_TYPE_OPTIONS = [
|
{ label: '自评', value: 1 },
|
{ label: '上级评', value: 2 },
|
];
|
|
/** 加载指标列表(仅在首次打开时) */
|
async function loadItems() {
|
items.value = await getAppraiseItemList(appraiseId.value!);
|
}
|
|
/** 切换员工时回填已有评分 */
|
async function handleEmployeeChange(item: { id?: number } | undefined) {
|
employeeId.value = item?.id;
|
comment.value = '';
|
if (!item?.id) {
|
items.value.forEach((it) => {
|
it.selfScore = undefined;
|
it.superiorScore = undefined;
|
});
|
return;
|
}
|
const result = await getAppraiseResult(appraiseId.value!, item.id);
|
if (result?.items) {
|
items.value.forEach((it) => {
|
const detail = result.items!.find((ri) => ri.itemId === it.id);
|
it.selfScore = detail?.selfScore;
|
it.superiorScore = detail?.superiorScore;
|
});
|
comment.value = result.comment ?? '';
|
} else {
|
items.value.forEach((it) => {
|
it.selfScore = undefined;
|
it.superiorScore = undefined;
|
});
|
}
|
}
|
|
const [Modal, modalApi] = useVbenModal({
|
async onConfirm() {
|
if (!employeeId.value) {
|
message.warning('请选择员工');
|
return;
|
}
|
modalApi.lock();
|
try {
|
await saveAppraiseResult({
|
appraiseId: appraiseId.value!,
|
employeeId: employeeId.value!,
|
comment: comment.value,
|
items: items.value.map((item) => ({
|
itemId: item.id!,
|
selfScore: item.selfScore,
|
superiorScore: item.superiorScore,
|
})),
|
});
|
await modalApi.close();
|
emit('success');
|
message.success('评分保存成功,已自动计算综合得分');
|
} finally {
|
modalApi.unlock();
|
}
|
},
|
async onOpenChange(isOpen: boolean) {
|
if (!isOpen) {
|
appraiseId.value = undefined;
|
employeeId.value = undefined;
|
items.value = [];
|
comment.value = '';
|
return;
|
}
|
const data = modalApi.getData<{ id: number }>();
|
appraiseId.value = data?.id;
|
modalApi.lock();
|
try {
|
await loadItems();
|
} finally {
|
modalApi.unlock();
|
}
|
},
|
});
|
</script>
|
|
<template>
|
<Modal title="员工考核评分" class="w-3/4">
|
<div class="mb-4 flex items-center gap-4">
|
<span class="shrink-0">考核员工:</span>
|
<HrmEmployeeSelect
|
:model-value="employeeId"
|
class="!w-72"
|
@change="handleEmployeeChange"
|
@update:model-value="(value: number | undefined) => (employeeId = value)"
|
/>
|
</div>
|
<a-table
|
:data-source="items"
|
:pagination="false"
|
:scroll="{ y: 300 }"
|
bordered
|
row-key="id"
|
size="small"
|
>
|
<a-table-column title="指标名称" min-width="180">
|
<template #default="{ record }">
|
<span>{{ record.itemName }}</span>
|
</template>
|
</a-table-column>
|
<a-table-column title="权重" width="90">
|
<template #default="{ record }">
|
<span>{{ record.weight }}</span>
|
</template>
|
</a-table-column>
|
<a-table-column title="评分人" width="90">
|
<template #default="{ record }">
|
<span>{{ record.scorerType === 1 ? '自评' : '上级评' }}</span>
|
</template>
|
</a-table-column>
|
<a-table-column title="自评得分" width="130">
|
<template #default="{ record }">
|
<a-input-number
|
v-model:value="record.selfScore"
|
:min="0"
|
:max="100"
|
:precision="1"
|
class="!w-full"
|
placeholder="自评得分"
|
/>
|
</template>
|
</a-table-column>
|
<a-table-column title="上级评得分" width="130">
|
<template #default="{ record }">
|
<a-input-number
|
v-model:value="record.superiorScore"
|
:min="0"
|
:max="100"
|
:precision="1"
|
class="!w-full"
|
placeholder="上级评得分"
|
/>
|
</template>
|
</a-table-column>
|
<a-table-column title="评分标准" min-width="180">
|
<template #default="{ record }">
|
<span class="text-xs text-gray-400">{{ record.scoringStandard || '-' }}</span>
|
</template>
|
</a-table-column>
|
</a-table>
|
<div class="mt-3">
|
<span class="mr-2">评语:</span>
|
<a-textarea
|
v-model:value="comment"
|
:rows="2"
|
placeholder="请输入评语"
|
class="!w-full"
|
/>
|
</div>
|
</Modal>
|
</template>
|