# Conflicts: # AGENTS.md # README.md # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/domain/AihrPracticeDto.java # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrOrgSyncService.java # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrPracticeSeedService.java # backend/ruoyi-modules/ruoyi-aihr/src/main/java/org/dromara/aihr/service/AihrUploadQueueService.java # backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrOrgSyncServiceTest.java # backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrPracticeSeedServiceTest.java # backend/ruoyi-modules/ruoyi-aihr/src/test/java/org/dromara/aihr/service/AihrUploadQueueServiceTest.java # docs/20260708/uni-app用户侧前端重建计划.md # docs/API_INTEGRATION.md # docs/BRD_IMPLEMENTATION_AUDIT.md # docs/BRD_PRODUCTION_MIGRATION_RUNBOOK.md # docs/DEMO_ACCEPTANCE.md # docs/DEV_SETUP.md # docs/FIGMA_IMPLEMENTATION_MATRIX.md # docs/README.md # frontend/src/views/knowledge/processing.vue # mobile-uni/src/pages/supervisor/assign/index.vue # mobile-uni/src/pages/supervisor/index/index.vue # mobile-uni/src/pages/supervisor/profile/index.vue # mobile-uni/src/pages/supervisor/review/index.vue # mobile-uni/src/pages/supervisor/reviews/index.vue # mobile-uni/src/pages/supervisor/team/index.vue # mobile-uni/src/pages/user/cases/index.vue # mobile-uni/src/pages/user/practice/index.vue # mobile-uni/src/pages/user/profile/index.vue # mobile-uni/src/pages/user/sop/index.vue # mobile-uni/src/pages/user/today/index.vue # mobile-uni/src/types/api.ts # scripts/tests/aihr-schema-migrations.test.sh
253 lines
6.0 KiB
TypeScript
253 lines
6.0 KiB
TypeScript
import request from '@/utils/request';
|
|
|
|
type ApiResult<T> = {
|
|
code: number;
|
|
msg: string;
|
|
data: T;
|
|
};
|
|
|
|
export type SopDoc = {
|
|
title: string;
|
|
desc: string;
|
|
hit: string;
|
|
type: string;
|
|
};
|
|
|
|
export type SopSnippet = {
|
|
title: string;
|
|
text: string;
|
|
fragmentId?: number | null;
|
|
spaceCode?: string | null;
|
|
sourceType?: string;
|
|
};
|
|
|
|
export type SopRecord = {
|
|
title: string;
|
|
category: string;
|
|
version: string;
|
|
status: string;
|
|
owner: string;
|
|
summary: string;
|
|
source?: 'demo' | 'uploaded' | string;
|
|
};
|
|
|
|
export type SopSearchResponse = {
|
|
requestId?: string;
|
|
queryText: string;
|
|
category: string;
|
|
answer: string;
|
|
reference: string;
|
|
docs: SopDoc[];
|
|
snippets: SopSnippet[];
|
|
training: string[];
|
|
records: SopRecord[];
|
|
keyPoints?: string[];
|
|
cautions?: string[];
|
|
promptVersion?: string | null;
|
|
reviewId?: number;
|
|
citations?: SopCitation[];
|
|
usedSpaceCodes?: string[];
|
|
noEvidence?: boolean;
|
|
data?: unknown;
|
|
};
|
|
|
|
export type SopCitation = {
|
|
spaceCode?: string | null;
|
|
sourceType: string;
|
|
docId?: string | null;
|
|
title: string;
|
|
snippet: string;
|
|
fragmentId?: number | null;
|
|
};
|
|
|
|
type UnifiedQueryResponse = {
|
|
requestId: string;
|
|
queryText: string;
|
|
answer: string;
|
|
citations: SopCitation[];
|
|
usedSpaceCodes: string[];
|
|
noEvidence: boolean;
|
|
promptVersion?: string | null;
|
|
legacy?: SopSearchResponse | null;
|
|
data?: unknown;
|
|
};
|
|
|
|
export type SopReviewResponse = {
|
|
id: number;
|
|
usable: boolean | null;
|
|
status: string;
|
|
reviewedAt: string;
|
|
promptVersion?: string | null;
|
|
};
|
|
|
|
export type AnswerFeedbackItem = {
|
|
id: number;
|
|
queryText: string;
|
|
queryNorm: string;
|
|
fragmentId: number;
|
|
verdict: string;
|
|
feedbackReasonCodes?: string | null;
|
|
feedbackComment?: string | null;
|
|
category: string;
|
|
position: string;
|
|
source: string;
|
|
reviewId?: number | null;
|
|
reviewStatus: string;
|
|
reviewer?: string | null;
|
|
reviewedTime?: string | null;
|
|
createTime: string;
|
|
updateTime: string;
|
|
};
|
|
|
|
export type AnswerFeedbackReviewResponse = {
|
|
id: number;
|
|
reviewStatus: string;
|
|
reviewer?: string | null;
|
|
reviewedTime?: string | null;
|
|
};
|
|
|
|
export type SopUploadResponse = {
|
|
docId: string;
|
|
ossId: number;
|
|
fileName: string;
|
|
category: string;
|
|
fragments: number;
|
|
summary: string;
|
|
tags: string[];
|
|
snippets: SopSnippet[];
|
|
};
|
|
|
|
export function searchKnowledgeSop(data: {
|
|
queryText: string;
|
|
category: string;
|
|
position?: string;
|
|
source?: string;
|
|
limit: number;
|
|
spaceCodes?: string[];
|
|
toolCode?: 'MY_PRACTICE_SUMMARY' | 'TEAM_PRACTICE_SUMMARY';
|
|
}): Promise<ApiResult<SopSearchResponse>> {
|
|
return request<unknown, ApiResult<UnifiedQueryResponse>>({
|
|
url: '/api/knowledge/query',
|
|
method: 'post',
|
|
data,
|
|
headers: { repeatSubmit: false }
|
|
}).then((result) => {
|
|
const response = result.data;
|
|
const legacy = response.legacy || ({} as SopSearchResponse);
|
|
const snippets = legacy.snippets?.length
|
|
? legacy.snippets
|
|
: (response.citations || []).map((item) => ({
|
|
title: item.title,
|
|
text: item.snippet,
|
|
fragmentId: item.fragmentId,
|
|
spaceCode: item.spaceCode,
|
|
sourceType: item.sourceType
|
|
}));
|
|
return {
|
|
...result,
|
|
data: {
|
|
...legacy,
|
|
requestId: response.requestId,
|
|
queryText: response.queryText,
|
|
category: legacy.category || data.category || 'sop',
|
|
answer: response.answer,
|
|
reference: legacy.reference || response.citations.map((item) => item.title).join('、'),
|
|
docs: legacy.docs || [],
|
|
snippets,
|
|
training: legacy.training || [],
|
|
records: legacy.records || [],
|
|
citations: response.citations || [],
|
|
usedSpaceCodes: response.usedSpaceCodes || [],
|
|
noEvidence: response.noEvidence,
|
|
promptVersion: response.promptVersion,
|
|
data: response.data
|
|
}
|
|
};
|
|
});
|
|
}
|
|
|
|
export function uploadKnowledgeDoc(data: FormData): Promise<ApiResult<SopUploadResponse>> {
|
|
return request({
|
|
url: '/api/knowledge/doc/upload',
|
|
method: 'post',
|
|
data,
|
|
timeout: 180000,
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|
|
|
|
export function reviewKnowledgeSop(id: number, data: { usable: boolean; reviewer?: string; note?: string }): Promise<ApiResult<SopReviewResponse>> {
|
|
return request({
|
|
url: `/api/knowledge/reviews/${id}`,
|
|
method: 'post',
|
|
data,
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|
|
|
|
export function listAnswerFeedback(status = '待复核', limit = 50): Promise<ApiResult<AnswerFeedbackItem[]>> {
|
|
return request({
|
|
url: '/api/knowledge/answer-feedback',
|
|
method: 'get',
|
|
params: { status, limit },
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|
|
|
|
export function reviewAnswerFeedback(id: number): Promise<ApiResult<AnswerFeedbackReviewResponse>> {
|
|
return request({
|
|
url: `/api/knowledge/answer-feedback/${id}/review`,
|
|
method: 'post',
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|
|
|
|
export type UploadEnqueueResponse = {
|
|
itemId: number;
|
|
batchId: string;
|
|
fileName: string;
|
|
status: string;
|
|
};
|
|
|
|
export type UploadItem = {
|
|
id: number;
|
|
batchId: string;
|
|
fileName: string;
|
|
category: string;
|
|
spaceCodes: string[];
|
|
status: number;
|
|
statusLabel: string;
|
|
error: string | null;
|
|
docId: string | null;
|
|
fragmentCount: number | null;
|
|
updatedAt: string;
|
|
};
|
|
|
|
/** 批量上传走异步队列:接口只暂存+入队即返回,解析/归类/向量化由后台 worker 处理。 */
|
|
export function uploadKnowledgeDocAsync(data: FormData): Promise<ApiResult<UploadEnqueueResponse>> {
|
|
return request({
|
|
url: '/api/knowledge/doc/upload-async',
|
|
method: 'post',
|
|
data,
|
|
timeout: 60000,
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|
|
|
|
export function listUploadItems(batchId: string): Promise<ApiResult<UploadItem[]>> {
|
|
return request({
|
|
url: '/api/knowledge/doc/upload-items',
|
|
method: 'get',
|
|
params: { batchId },
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|
|
|
|
export function retryUploadItem(id: number): Promise<ApiResult<UploadItem>> {
|
|
return request({
|
|
url: `/api/knowledge/doc/upload-items/${id}/retry`,
|
|
method: 'post',
|
|
headers: { repeatSubmit: false }
|
|
});
|
|
}
|