feat(我的绩效): 开发我的绩效功能。
fix(加班申请、工作报告): 重构加班申请在审批时的样式,工作报告在新增时的对话框、报告详情页的样式。
This commit is contained in:
@@ -6,6 +6,7 @@ export * from './notice';
|
||||
export * from './notify-message';
|
||||
export * from './object-context';
|
||||
export * from './overtime-application';
|
||||
export * from './performance';
|
||||
export * from './personal-item';
|
||||
export * from './product';
|
||||
export * from './project';
|
||||
|
||||
501
src/service/api/performance.ts
Normal file
501
src/service/api/performance.ts
Normal file
@@ -0,0 +1,501 @@
|
||||
import dayjs from 'dayjs';
|
||||
import { WEB_SERVICE_PREFIX } from '@/constants/service';
|
||||
import { request } from '../request';
|
||||
import {
|
||||
type ServiceRequestResult,
|
||||
mapServiceResult,
|
||||
normalizeNullableStringId,
|
||||
normalizeStringId,
|
||||
safeJsonRequestConfig
|
||||
} from './shared';
|
||||
|
||||
const TEMPLATE_PREFIX = `${WEB_SERVICE_PREFIX}/project/performance-templates`;
|
||||
const SHEET_PREFIX = `${WEB_SERVICE_PREFIX}/project/performance-sheets`;
|
||||
const TEAM_PREFIX = `${SHEET_PREFIX}/team`;
|
||||
|
||||
type StringIdResponse = string | number;
|
||||
|
||||
type TemplateResponse = Omit<Api.Performance.Template.Template, 'id' | 'fileId' | 'uploadUserId' | 'activeFlag'> & {
|
||||
id: StringIdResponse;
|
||||
fileId: StringIdResponse;
|
||||
uploadUserId: StringIdResponse;
|
||||
activeFlag?: boolean | number | string | null;
|
||||
};
|
||||
|
||||
type TemplatePageResponse = {
|
||||
total: number | string;
|
||||
list: TemplateResponse[];
|
||||
};
|
||||
|
||||
type SheetResponse = Omit<
|
||||
Api.Performance.Sheet.Sheet,
|
||||
'id' | 'employeeId' | 'employeeDeptId' | 'managerId' | 'templateId' | 'fileId'
|
||||
> & {
|
||||
id: StringIdResponse;
|
||||
employeeId: StringIdResponse;
|
||||
employeeDeptId: StringIdResponse;
|
||||
managerId: StringIdResponse;
|
||||
templateId: StringIdResponse;
|
||||
fileId?: StringIdResponse | null;
|
||||
};
|
||||
|
||||
type SheetPageResponse = {
|
||||
total: number | string;
|
||||
list: SheetResponse[];
|
||||
};
|
||||
|
||||
type StatusLogResponse = Omit<Api.Performance.Sheet.StatusLog, 'id' | 'sheetId' | 'operatorUserId'> & {
|
||||
id: StringIdResponse;
|
||||
sheetId: StringIdResponse;
|
||||
operatorUserId: StringIdResponse;
|
||||
};
|
||||
|
||||
type ResponseRecordResponse = Omit<
|
||||
Api.Performance.Sheet.ResponseRecord,
|
||||
'id' | 'sheetId' | 'statusLogId' | 'responderUserId'
|
||||
> & {
|
||||
id: StringIdResponse;
|
||||
sheetId: StringIdResponse;
|
||||
statusLogId: StringIdResponse;
|
||||
responderUserId: StringIdResponse;
|
||||
};
|
||||
|
||||
type MonthlyResultResponse = Omit<Api.Performance.Sheet.MonthlyResult, 'sheetId' | 'employeeId'> & {
|
||||
sheetId?: StringIdResponse | null;
|
||||
employeeId: StringIdResponse;
|
||||
};
|
||||
|
||||
type TeamSummaryResponse = Omit<
|
||||
Api.Performance.Team.Summary,
|
||||
| 'totalSheetCount'
|
||||
| 'pendingSendCount'
|
||||
| 'pendingConfirmCount'
|
||||
| 'pendingSendUsers'
|
||||
| 'pendingConfirmUsers'
|
||||
| 'deptOrgAverages'
|
||||
> & {
|
||||
totalSheetCount?: number | string | null;
|
||||
pendingSendCount?: number | string | null;
|
||||
pendingConfirmCount?: number | string | null;
|
||||
pendingSendUsers?: Array<
|
||||
Omit<Api.Performance.Team.PendingSendUser, 'userId' | 'managerUserId' | 'sheetId'> & {
|
||||
userId: StringIdResponse;
|
||||
managerUserId: StringIdResponse;
|
||||
sheetId?: StringIdResponse | null;
|
||||
}
|
||||
> | null;
|
||||
pendingConfirmUsers?: Array<
|
||||
Omit<Api.Performance.Team.PendingConfirmUser, 'userId' | 'sheetId'> & {
|
||||
userId: StringIdResponse;
|
||||
sheetId: StringIdResponse;
|
||||
}
|
||||
> | null;
|
||||
deptOrgAverages?: Array<
|
||||
Omit<Api.Performance.Team.DeptOrgAverage, 'deptId' | 'confirmedCount'> & {
|
||||
deptId: StringIdResponse;
|
||||
confirmedCount?: number | string | null;
|
||||
}
|
||||
> | null;
|
||||
};
|
||||
|
||||
function normalizeBooleanFlag(value: boolean | number | string | null | undefined) {
|
||||
if (typeof value === 'boolean') return value;
|
||||
if (typeof value === 'number') return value === 1;
|
||||
if (typeof value === 'string') {
|
||||
const normalized = value.trim().toLowerCase();
|
||||
|
||||
return !['', '0', 'false', 'n', 'no'].includes(normalized);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function normalizeTotal(value: number | string | null | undefined) {
|
||||
const total = Number(value ?? 0);
|
||||
|
||||
return Number.isFinite(total) ? Math.max(0, total) : 0;
|
||||
}
|
||||
|
||||
function normalizeTemplate(response: TemplateResponse): Api.Performance.Template.Template {
|
||||
return {
|
||||
...response,
|
||||
id: normalizeStringId(response.id),
|
||||
fileId: normalizeStringId(response.fileId),
|
||||
uploadUserId: normalizeStringId(response.uploadUserId),
|
||||
activeFlag: normalizeBooleanFlag(response.activeFlag),
|
||||
remark: response.remark ?? null,
|
||||
scoreCellMapping: response.scoreCellMapping ?? null
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeSheet(response: SheetResponse): Api.Performance.Sheet.Sheet {
|
||||
return {
|
||||
...response,
|
||||
id: normalizeStringId(response.id),
|
||||
employeeId: normalizeStringId(response.employeeId),
|
||||
employeeDeptId: normalizeStringId(response.employeeDeptId),
|
||||
managerId: normalizeStringId(response.managerId),
|
||||
templateId: normalizeStringId(response.templateId),
|
||||
fileId: normalizeNullableStringId(response.fileId),
|
||||
fileName: response.fileName ?? null,
|
||||
statusName: response.statusName || response.statusCode,
|
||||
actualScoreTotal: response.actualScoreTotal ?? null,
|
||||
baseScoreTotal: response.baseScoreTotal ?? null,
|
||||
extraScoreTotal: response.extraScoreTotal ?? null,
|
||||
sentTime: response.sentTime ?? null,
|
||||
confirmedTime: response.confirmedTime ?? null,
|
||||
rejectedTime: response.rejectedTime ?? null,
|
||||
lastStatusReason: response.lastStatusReason ?? null,
|
||||
createTime: response.createTime ?? null,
|
||||
updateTime: response.updateTime ?? null
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeStatusLog(response: StatusLogResponse): Api.Performance.Sheet.StatusLog {
|
||||
return {
|
||||
...response,
|
||||
id: normalizeStringId(response.id),
|
||||
sheetId: normalizeStringId(response.sheetId),
|
||||
operatorUserId: normalizeStringId(response.operatorUserId),
|
||||
reason: response.reason ?? null,
|
||||
remark: response.remark ?? null
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeResponseRecord(response: ResponseRecordResponse): Api.Performance.Sheet.ResponseRecord {
|
||||
return {
|
||||
...response,
|
||||
id: normalizeStringId(response.id),
|
||||
sheetId: normalizeStringId(response.sheetId),
|
||||
statusLogId: normalizeStringId(response.statusLogId),
|
||||
responderUserId: normalizeStringId(response.responderUserId),
|
||||
opinion: response.opinion ?? null
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeMonthlyResult(response: MonthlyResultResponse): Api.Performance.Sheet.MonthlyResult {
|
||||
return {
|
||||
...response,
|
||||
sheetId: normalizeNullableStringId(response.sheetId),
|
||||
employeeId: normalizeStringId(response.employeeId),
|
||||
actualScoreTotal: response.actualScoreTotal ?? null,
|
||||
baseScoreTotal: response.baseScoreTotal ?? null,
|
||||
extraScoreTotal: response.extraScoreTotal ?? null,
|
||||
statusCode: response.statusCode ?? null
|
||||
};
|
||||
}
|
||||
|
||||
function normalizeTeamSummary(response: TeamSummaryResponse): Api.Performance.Team.Summary {
|
||||
return {
|
||||
...response,
|
||||
totalSheetCount: normalizeTotal(response.totalSheetCount),
|
||||
pendingSendCount: normalizeTotal(response.pendingSendCount),
|
||||
pendingConfirmCount: normalizeTotal(response.pendingConfirmCount),
|
||||
pendingSendUsers: (response.pendingSendUsers || []).map(item => ({
|
||||
...item,
|
||||
userId: normalizeStringId(item.userId),
|
||||
managerUserId: normalizeStringId(item.managerUserId),
|
||||
sheetId: normalizeNullableStringId(item.sheetId),
|
||||
statusCode: item.statusCode ?? null
|
||||
})),
|
||||
pendingConfirmUsers: (response.pendingConfirmUsers || []).map(item => ({
|
||||
...item,
|
||||
userId: normalizeStringId(item.userId),
|
||||
sheetId: normalizeStringId(item.sheetId),
|
||||
sentTime: item.sentTime ?? null
|
||||
})),
|
||||
deptOrgAverages: (response.deptOrgAverages || []).map(item => ({
|
||||
...item,
|
||||
deptId: normalizeStringId(item.deptId),
|
||||
averageScore: item.averageScore ?? null,
|
||||
confirmedCount: normalizeTotal(item.confirmedCount)
|
||||
}))
|
||||
};
|
||||
}
|
||||
|
||||
function appendValue(query: URLSearchParams, key: string, value: unknown) {
|
||||
if (value === null || value === undefined || value === '') return;
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
if (!value.length) {
|
||||
query.append(key, '');
|
||||
return;
|
||||
}
|
||||
|
||||
value.forEach(item => appendValue(query, key, item));
|
||||
return;
|
||||
}
|
||||
|
||||
query.append(key, String(value));
|
||||
}
|
||||
|
||||
export function formatToYYYYMM(value?: string | null) {
|
||||
if (!value) return '';
|
||||
|
||||
const d = dayjs(value);
|
||||
|
||||
return d.isValid() ? d.format('YYYY-MM') : value.slice(0, 7);
|
||||
}
|
||||
|
||||
function createSheetQuery(params: Api.Performance.Sheet.SearchParams = {}) {
|
||||
const query = new URLSearchParams();
|
||||
|
||||
query.append('pageNo', String(params.pageNo ?? 1));
|
||||
query.append('pageSize', String(params.pageSize ?? 10));
|
||||
appendValue(query, 'employeeIds', params.employeeIds);
|
||||
// 将 periodMonthRange 拆为 periodMonthStart / periodMonthEnd
|
||||
if (params.periodMonthRange?.length === 2) {
|
||||
appendValue(query, 'periodMonthStart', formatToYYYYMM(params.periodMonthRange[0]));
|
||||
appendValue(query, 'periodMonthEnd', formatToYYYYMM(params.periodMonthRange[1]));
|
||||
}
|
||||
// employeeId 单选追加到 employeeIds
|
||||
if (params.employeeId) {
|
||||
query.append('employeeIds', params.employeeId);
|
||||
}
|
||||
appendValue(query, 'employeeDeptId', params.employeeDeptId);
|
||||
appendValue(query, 'managerName', params.managerName);
|
||||
appendValue(query, 'statusCode', params.statusCode);
|
||||
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
function createTemplateQuery(params: Api.Performance.Template.SearchParams = {}) {
|
||||
const query = new URLSearchParams();
|
||||
|
||||
query.append('pageNo', String(params.pageNo ?? 1));
|
||||
query.append('pageSize', String(params.pageSize ?? 10));
|
||||
appendValue(query, 'templateName', params.templateName);
|
||||
appendValue(query, 'activeFlag', params.activeFlag);
|
||||
|
||||
return query.toString();
|
||||
}
|
||||
|
||||
export async function fetchPerformanceTemplateCurrent() {
|
||||
const result = await request<TemplateResponse | null>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${TEMPLATE_PREFIX}/current`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<TemplateResponse | null>, data =>
|
||||
data ? normalizeTemplate(data) : null
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchPerformanceTemplatePage(params: Api.Performance.Template.SearchParams = {}) {
|
||||
const query = createTemplateQuery(params);
|
||||
const result = await request<TemplatePageResponse>({
|
||||
...safeJsonRequestConfig,
|
||||
url: query ? `${TEMPLATE_PREFIX}/page?${query}` : `${TEMPLATE_PREFIX}/page`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<TemplatePageResponse>, data => ({
|
||||
total: normalizeTotal(data.total),
|
||||
list: data.list.map(normalizeTemplate)
|
||||
}));
|
||||
}
|
||||
|
||||
export async function uploadPerformanceTemplate(data: Api.Performance.Template.UploadParams) {
|
||||
const result = await request<StringIdResponse>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${TEMPLATE_PREFIX}/upload`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
|
||||
}
|
||||
|
||||
export function activatePerformanceTemplate(id: string) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${TEMPLATE_PREFIX}/${id}/activate`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchPerformanceSheetPage(params: Api.Performance.Sheet.SearchParams = {}) {
|
||||
const query = createSheetQuery(params);
|
||||
const result = await request<SheetPageResponse>({
|
||||
...safeJsonRequestConfig,
|
||||
url: query ? `${SHEET_PREFIX}/page?${query}` : `${SHEET_PREFIX}/page`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<SheetPageResponse>, data => ({
|
||||
total: normalizeTotal(data.total),
|
||||
list: data.list.map(normalizeSheet)
|
||||
}));
|
||||
}
|
||||
|
||||
export async function fetchPerformanceSheet(id: string) {
|
||||
const result = await request<SheetResponse>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<SheetResponse>, normalizeSheet);
|
||||
}
|
||||
|
||||
export async function createPerformanceSheet(data: Api.Performance.Sheet.CreateParams) {
|
||||
const result = await request<StringIdResponse>({
|
||||
...safeJsonRequestConfig,
|
||||
url: SHEET_PREFIX,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<StringIdResponse>, normalizeStringId);
|
||||
}
|
||||
|
||||
export function updatePerformanceSheetExcel(id: string, data: Api.Performance.Sheet.ExcelUpdateParams) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/excel`,
|
||||
method: 'put',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function deletePerformanceSheet(id: string) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}`,
|
||||
method: 'delete'
|
||||
});
|
||||
}
|
||||
|
||||
export function sendPerformanceSheet(id: string) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/send`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
export function resendPerformanceSheet(id: string) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/resend`,
|
||||
method: 'post'
|
||||
});
|
||||
}
|
||||
|
||||
export function confirmPerformanceSheet(id: string, data: Api.Performance.Sheet.StatusActionParams = {}) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/confirm`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function rejectPerformanceSheet(id: string, data: Api.Performance.Sheet.StatusActionParams) {
|
||||
return request<boolean>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/reject`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
|
||||
export function downloadPerformanceSheet(id: string) {
|
||||
return request<Blob, 'blob'>({
|
||||
url: `${SHEET_PREFIX}/${id}/download`,
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
export function batchDownloadPerformanceSheets(data: Api.Performance.Sheet.BatchDownloadParams) {
|
||||
return request<Blob, 'blob'>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/batch-download`,
|
||||
method: 'post',
|
||||
data,
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
export function exportPerformanceSheets(params: Api.Performance.Sheet.SearchParams = {}) {
|
||||
const query = createSheetQuery(params);
|
||||
|
||||
return request<Blob, 'blob'>({
|
||||
url: query ? `${SHEET_PREFIX}/export?${query}` : `${SHEET_PREFIX}/export`,
|
||||
method: 'get',
|
||||
responseType: 'blob'
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchPerformanceSheetStatusLogs(id: string) {
|
||||
const result = await request<StatusLogResponse[]>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/status-logs`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<StatusLogResponse[]>, data => data.map(normalizeStatusLog));
|
||||
}
|
||||
|
||||
export async function fetchPerformanceSheetResponseRecords(id: string) {
|
||||
const result = await request<ResponseRecordResponse[]>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/${id}/response-records`,
|
||||
method: 'get'
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<ResponseRecordResponse[]>, data =>
|
||||
data.map(normalizeResponseRecord)
|
||||
);
|
||||
}
|
||||
|
||||
export async function fetchPerformanceMonthlyResult(employeeId: string, periodMonth: string) {
|
||||
const result = await request<MonthlyResultResponse | null>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/monthly-result`,
|
||||
method: 'get',
|
||||
params: { employeeId, periodMonth }
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<MonthlyResultResponse | null>, data =>
|
||||
data ? normalizeMonthlyResult(data) : null
|
||||
);
|
||||
}
|
||||
|
||||
export function fetchPerformanceSheetStatusDict() {
|
||||
return request<Api.Performance.Sheet.StatusDict[]>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/status-dict`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
export function fetchPerformanceSheetStatusTransitions() {
|
||||
return request<Api.Performance.Sheet.StatusTransition[]>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${SHEET_PREFIX}/status-transitions`,
|
||||
method: 'get'
|
||||
});
|
||||
}
|
||||
|
||||
export async function fetchTeamPerformanceSummary(params: Api.Performance.Team.SummaryParams = {}) {
|
||||
const result = await request<TeamSummaryResponse>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${TEAM_PREFIX}/summary`,
|
||||
method: 'get',
|
||||
params
|
||||
});
|
||||
|
||||
return mapServiceResult(result as ServiceRequestResult<TeamSummaryResponse>, normalizeTeamSummary);
|
||||
}
|
||||
|
||||
export function remindTeamPerformance(data: Api.Performance.Team.RemindParams) {
|
||||
return request<Api.Performance.Team.RemindResult>({
|
||||
...safeJsonRequestConfig,
|
||||
url: `${TEAM_PREFIX}/remind`,
|
||||
method: 'post',
|
||||
data
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user