feat(performance): 新增绩效下签功能支持

- 在月报审批页面增加 sign-off 场景支持
- 添加绩效下签对话框组件实现批量下签功能
- 增加导入绩效压缩包和直接下签两种操作模式
- 实现电子签名预览和日期格式化显示功能
- 更新绩效权限配置增加下签相关权限
- 优化审批对话框标题和按钮文案显示
- 添加导入结果提示和文件验证功能
- 实现团队模式下的下签操作入口
- 完善绩效表格状态和操作权限判断逻辑
This commit is contained in:
dk
2026-07-19 18:21:14 +08:00
parent c2f9c922cf
commit 08fff8bbc5
17 changed files with 1523 additions and 116 deletions

View File

@@ -44,6 +44,15 @@ type SheetPageResponse = {
list: SheetResponse[];
};
type ImportZipResultResponse = Omit<Api.Performance.Sheet.ImportZipResult, 'messages'> & {
workbookCount?: number | string | null;
sheetCount?: number | string | null;
successCount?: number | string | null;
skippedCount?: number | string | null;
failedCount?: number | string | null;
messages?: string[] | null;
};
type StatusLogResponse = Omit<Api.Performance.Sheet.StatusLog, 'id' | 'sheetId' | 'operatorUserId'> & {
id: StringIdResponse;
sheetId: StringIdResponse;
@@ -144,6 +153,8 @@ function normalizeSheet(response: SheetResponse): Api.Performance.Sheet.Sheet {
fileId: normalizeNullableStringId(response.fileId),
fileName: response.fileName ?? null,
statusName: response.statusName || response.statusCode,
signOffStatus: response.signOffStatus ?? null,
signOffStatusName: response.signOffStatusName ?? null,
actualScoreTotal: response.actualScoreTotal ?? null,
baseScoreTotal: response.baseScoreTotal ?? null,
extraScoreTotal: response.extraScoreTotal ?? null,
@@ -282,6 +293,7 @@ function createSheetQuery(params: Api.Performance.Sheet.SearchParams = {}) {
appendValue(query, 'employeeDeptId', params.employeeDeptId);
appendValue(query, 'managerName', params.managerName);
appendValue(query, 'statusCode', params.statusCode);
appendValue(query, 'signOffStatus', params.signOffStatus);
return query.toString();
}
@@ -377,6 +389,46 @@ export async function createPerformanceSheet(data: Api.Performance.Sheet.CreateP
return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
}
export async function importPerformanceSheetZip(data: Api.Performance.Sheet.ImportZipParams) {
const formData = new FormData();
formData.append('file', data.file);
formData.append('periodMonth', data.periodMonth);
data.employeeIds?.forEach(id => {
formData.append('employeeIds', id);
});
const result = await request<ImportZipResultResponse>({
...safeJsonRequestConfig,
url: `${SHEET_PREFIX}/import-zip`,
method: 'post',
data: formData
});
return mapServiceResult(result as ServiceRequestResult<ImportZipResultResponse>, payload => ({
workbookCount: normalizeTotal(payload.workbookCount),
sheetCount: normalizeTotal(payload.sheetCount),
successCount: normalizeTotal(payload.successCount),
skippedCount: normalizeTotal(payload.skippedCount),
failedCount: normalizeTotal(payload.failedCount),
messages: payload.messages ?? []
}));
}
export async function signOffPerformanceSheets(data: Api.Performance.Sheet.SignOffParams) {
const result = await request<StringIdResponse>({
...safeJsonRequestConfig,
url: `${SHEET_PREFIX}/sign-off`,
method: 'post',
data: {
...data,
employeeIds: data.employeeIds && data.employeeIds.length ? data.employeeIds : undefined,
remark: data.remark?.trim() || undefined
}
});
return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
}
export function updatePerformanceSheetExcel(id: string, data: Api.Performance.Sheet.ExcelUpdateParams) {
return request<boolean>({
...safeJsonRequestConfig,