Files
prop-ai-hr/mobile-uni/src/services/work-report.ts
T

157 lines
4.5 KiB
TypeScript

import { apiRequest, apiUrl, authHeaders, readTextPayload } from './api';
export type WorkReportType = 'CASE' | 'VIDEO' | 'SOP' | 'KNOWLEDGE';
export interface WorkReportRecord {
id: number;
type: WorkReportType;
typeLabel: string;
title: string;
content: string;
attachmentName?: string;
attachmentOssId?: number | string;
status: 'PENDING' | 'APPROVED' | 'REJECTED';
statusLabel: string;
submitterName: string;
reviewNote?: string;
createdAt: string;
reviewedAt?: string;
}
export interface WorkReportAttachment {
ossId: number | string;
fileName: string;
}
export interface WorkReportDraft {
suggestedType: WorkReportType;
title: string;
content: string;
}
export interface OrganizeResponse extends WorkReportDraft {
missingQuestions: string[];
privacyWarnings: string[];
confidence: number;
notice?: string;
}
export const stableWorkReportRequestId = (current: string, create: () => string) => current || create();
export const isDefinitiveWorkReportRejection = (error: { statusCode?: number; bizCode?: number }) => {
const status = Number(error.statusCode || 0);
const bizCode = Number(error.bizCode || 0);
const isDefinitive = (code: number) => code >= 400 && code < 500 && ![408, 409, 425, 429].includes(code);
return isDefinitive(status) || isDefinitive(bizCode);
};
export const isCurrentWorkReportRequest = (
generation: number,
currentGeneration: number,
accountKey: string,
currentAccountKey: string
) => generation === currentGeneration && accountKey === currentAccountKey;
export const prepareWorkReportOrganizeInput = (
transcript: string,
currentDraft?: WorkReportDraft
): { transcript: string; currentDraft?: WorkReportDraft } => {
const addition = transcript.trim();
if (!currentDraft) return { transcript: addition };
const currentContent = currentDraft.content.trim();
const content = !currentContent
? addition
: !addition || currentContent === addition
? currentContent
: `${currentContent}\n${addition}`;
return {
transcript: '',
currentDraft: {
...currentDraft,
content
}
};
};
export const workReportTypes: Array<{ value: WorkReportType; label: string; desc: string; icon: string }> = [
{ value: 'CASE', label: '优秀案例', desc: '现场处理得好的真实案例', icon: '⭐' },
{ value: 'VIDEO', label: '操作视频', desc: '值得推广的操作演示视频', icon: '🎬' },
{ value: 'SOP', label: '完整SOP', desc: '整理好的完整工作流程', icon: '📋' },
{ value: 'KNOWLEDGE', label: '有用知识', desc: '对工作有帮助的经验知识', icon: '💡' }
];
export const submitWorkReport = (params: {
requestId: string;
type: WorkReportType;
title: string;
content: string;
attachmentOssId?: number | string;
attachmentName?: string;
}) =>
apiRequest<WorkReportRecord>({
url: '/api/aihr/work-report/reports',
method: 'POST',
data: params,
timeout: 20000
});
export const organizeWorkReport = (params: {
transcript: string;
currentDraft?: WorkReportDraft;
attachmentOssId?: number | string;
attachmentName?: string;
}) =>
apiRequest<OrganizeResponse>({
url: '/api/aihr/work-report/organize',
method: 'POST',
data: params,
timeout: 45000
});
export const listMyWorkReports = () =>
apiRequest<WorkReportRecord[]>({
url: '/api/aihr/work-report/reports/mine',
method: 'GET',
timeout: 15000
});
export const listReviewWorkReports = (status = '') =>
apiRequest<WorkReportRecord[]>({
url: `/api/aihr/work-report/reports${status ? `?status=${encodeURIComponent(status)}` : ''}`,
method: 'GET',
timeout: 15000
});
export const reviewWorkReport = (id: number, decision: 'APPROVE' | 'REJECT', note = '') =>
apiRequest<WorkReportRecord>({
url: `/api/aihr/work-report/reports/${id}/review`,
method: 'POST',
data: { decision, note },
timeout: 20000
});
export const uploadWorkReportAttachment = (
filePath: string,
onUploadTask?: (task: ReturnType<typeof uni.uploadFile> | null) => void
) =>
new Promise<WorkReportAttachment>((resolve, reject) => {
const task = uni.uploadFile({
url: apiUrl('/api/aihr/work-report/attachment'),
filePath,
name: 'file',
header: authHeaders(false),
success: (response) => {
try {
resolve(readTextPayload<WorkReportAttachment>(response.statusCode, response.data));
} catch (error) {
reject(error);
}
},
fail: () => reject(new Error('附件上传失败')),
complete: () => onUploadTask?.(null)
});
onUploadTask?.(task);
});