feat(performance、notify、weekly): 添加绩效考核功能、通知跳转链接、优化工作日志分割逻辑。

This commit is contained in:
dk
2026-07-07 16:51:34 +08:00
parent c1f710fbd8
commit a0dcd39c23
6 changed files with 330 additions and 34 deletions

View File

@@ -4,9 +4,11 @@ import { computed, nextTick, reactive, ref, watch } from 'vue';
import type { FormRules } from 'element-plus';
import dayjs from 'dayjs';
import { RDMS_REQ_PRIORITY_DICT_CODE, RDMS_TASK_ITEM_TYPE_DICT_CODE } from '@/constants/dict';
import { fetchPerformanceSheetPage } from '@/service/api';
import { useForm, useFormRules } from '@/hooks/common/form';
import { useDict } from '@/hooks/business/dict';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import PerformanceExcelEditorDrawer from '../../../my-performance/modules/performance-excel-editor-drawer.vue';
import {
type WorkReportStructuredSection,
type WorkReportStructuredTask,
@@ -73,6 +75,10 @@ const EMPTY_TEXT = '';
const { getLabel: getTaskItemTypeLabel } = useDict(RDMS_TASK_ITEM_TYPE_DICT_CODE);
const { dictData: priorityDictData, getLabel: getPriorityLabel } = useDict(RDMS_REQ_PRIORITY_DICT_CODE);
const todayText = computed(() => dayjs().format('YYYY-MM-DD'));
const performanceDrawerVisible = ref(false);
const performanceDrawerLoading = ref(false);
const performanceDrawerMode = ref<'create' | 'edit'>('create');
const performanceDrawerRow = ref<Api.Performance.Sheet.Sheet | null>(null);
const auditDialogVisible = ref(false);
const auditForm = reactive({
@@ -90,7 +96,6 @@ const pageValidationModel = reactive({
}
});
const pageRules: FormRules = {
meetingDate: [createRequiredRule('请选择面谈时间')],
performanceResult: [
createRequiredRule('请输入绩效考核结果'),
{
@@ -177,6 +182,24 @@ const performanceForm = reactive({
}
});
const performanceTargetOption = computed(() => {
const reporterId = props.baseInfo?.reporterId || '';
const reporterName = props.baseInfo?.reporterName || '';
if (!reporterId || !reporterName) return [];
return [{ label: reporterName, value: reporterId }];
});
const performanceInitialEmployeeId = computed(() => props.baseInfo?.reporterId || '');
const performanceInitialPeriodMonth = computed(() => {
const periodDate = props.baseInfo?.periodStartDate || props.baseInfo?.periodEndDate || '';
if (!periodDate) return '';
const targetMonth = dayjs(periodDate);
return targetMonth.isValid() ? targetMonth.format('YYYY-MM') : '';
});
/** 绩效分数输入限制0-100最多一位小数 */
function handlePerformanceScoreInput(value: string) {
// 只允许数字和一个小数点
@@ -563,6 +586,37 @@ function openAuditDialog() {
});
}
async function openPerformanceDrawer() {
const reporterId = props.baseInfo?.reporterId || '';
const periodMonth = performanceInitialPeriodMonth.value;
performanceDrawerMode.value = 'create';
performanceDrawerRow.value = null;
if (reporterId && periodMonth) {
performanceDrawerLoading.value = true;
const { error, data } = await fetchPerformanceSheetPage({
pageNo: 1,
pageSize: 1,
employeeId: reporterId,
periodMonthRange: [periodMonth, periodMonth]
});
performanceDrawerLoading.value = false;
const existingSheet = !error && data?.list?.length ? data.list[0] : null;
if (existingSheet) {
performanceDrawerMode.value = 'edit';
performanceDrawerRow.value = existingSheet;
}
}
performanceDrawerVisible.value = true;
}
function handlePerformanceSaved(payload: { actualScoreTotal: string }) {
patchApproval('performanceResult', payload.actualScoreTotal);
}
watch(rejectOpinionRequired, async () => {
if (!auditDialogVisible.value) return;
@@ -614,10 +668,7 @@ watch(
<ElInput v-model="mainForm.supervisor" disabled />
</div>
<div class="field field-form-item">
<label>
面谈时间
<span class="field-required-mark">*</span>
</label>
<label>面谈时间</label>
<ElFormItem class="field-inline-form-item" prop="meetingDate">
<ElDatePicker v-model="mainForm.meetingDate" type="date" value-format="YYYY-MM-DD" style="width: 100%" />
</ElFormItem>
@@ -730,12 +781,25 @@ watch(
<span class="field-required-mark">*</span>
</div>
<ElFormItem class="performance-inline-form-item" prop="performanceResult">
<ElInput
v-model="performanceForm.score"
class="performance-input"
placeholder="请输入考核分数"
@input="handlePerformanceScoreInput"
/>
<div class="performance-input-group">
<ElInput
v-model="performanceForm.score"
class="performance-input"
placeholder="请输入考核分数"
readonly
@input="handlePerformanceScoreInput"
/>
<ElButton
plain
size="small"
type="primary"
:loading="performanceDrawerLoading"
:disabled="!performanceTargetOption.length"
@click="openPerformanceDrawer"
>
填写绩效
</ElButton>
</div>
</ElFormItem>
</div>
</div>
@@ -871,6 +935,18 @@ watch(
</ElForm>
</div>
</BusinessFormDialog>
<PerformanceExcelEditorDrawer
v-model:visible="performanceDrawerVisible"
:row-data="performanceDrawerRow"
:mode="performanceDrawerMode"
:subordinate-options="performanceTargetOption"
:initial-employee-id="performanceInitialEmployeeId"
:initial-period-month="performanceInitialPeriodMonth"
hide-draft-action
@saved="handlePerformanceSaved"
@saved-and-sent="handlePerformanceSaved"
/>
</div>
</template>
@@ -1794,13 +1870,19 @@ watch(
flex: 0 0 auto;
}
.performance-input-group {
display: inline-flex;
align-items: center;
gap: 12px;
}
.performance-input {
width: 200px;
}
.performance-input :deep(.el-input__wrapper) {
box-shadow: none !important;
background: transparent;
background: #f8fafc;
border-bottom: 1px solid #e2e8f0;
border-radius: 0;
padding: 0 4px;
@@ -1812,6 +1894,10 @@ watch(
text-align: center;
}
.performance-input :deep(.el-input__inner[readonly]) {
cursor: default;
}
.performance-input :deep(.el-input__inner::placeholder) {
color: #cbd5e1;
font-weight: 400;