fix(pkb): fix create KB and upload issues - remove simulated upload, fix department mapping, add upload modal

Fixed issues:
- Remove simulateUpload function from DashboardPage Step 3
- Map department to description field when creating KB
- Add upload modal in WorkspacePage knowledge assets tab
- Fix DocumentUpload import path (../../stores to ../stores)

Known issue: Dify API validation error during document upload (file uploaded but DB record failed, needs investigation)

Testing: KB creation works, upload dialog opens correctly
This commit is contained in:
2026-01-13 13:17:20 +08:00
parent d595037316
commit 4088275290
280 changed files with 4344 additions and 150 deletions

View File

@@ -9,6 +9,17 @@ import { logger } from '../../../common/logging/index.js';
import * as XLSX from 'xlsx';
import { startScreeningTask } from '../services/screeningService.js';
/**
* 获取用户ID从JWT Token中获取
*/
function getUserId(request: FastifyRequest): string {
const userId = (request as any).user?.userId;
if (!userId) {
throw new Error('User not authenticated');
}
return userId;
}
/**
* 导入文献从Excel或JSON
*/
@@ -17,7 +28,7 @@ export async function importLiteratures(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId, literatures } = request.body;
// 验证项目归属
@@ -90,7 +101,7 @@ export async function importLiteraturesFromExcel(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
// 获取上传的文件
const data = await request.file();
@@ -176,7 +187,7 @@ export async function getLiteratures(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
const { page = 1, limit = 50 } = request.query;
@@ -239,7 +250,7 @@ export async function deleteLiterature(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { literatureId } = request.params;
// 验证文献归属

View File

@@ -7,16 +7,26 @@ import { CreateScreeningProjectDto } from '../types/index.js';
import { prisma } from '../../../config/database.js';
import { logger } from '../../../common/logging/index.js';
/**
* 获取用户ID从JWT Token中获取
*/
function getUserId(request: FastifyRequest): string {
const userId = (request as any).user?.userId;
if (!userId) {
throw new Error('User not authenticated');
}
return userId;
}
/**
* 创建筛选项目
*/
export async function createProject(
request: FastifyRequest<{ Body: CreateScreeningProjectDto & { userId?: string } }>,
request: FastifyRequest<{ Body: CreateScreeningProjectDto }>,
reply: FastifyReply
) {
try {
// 临时测试模式优先从JWT获取否则从请求体获取
const userId = (request as any).userId || (request.body as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectName, picoCriteria, inclusionCriteria, exclusionCriteria, screeningConfig } = request.body;
// 验证必填字段
@@ -65,7 +75,7 @@ export async function createProject(
*/
export async function getProjects(request: FastifyRequest, reply: FastifyReply) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const projects = await prisma.aslScreeningProject.findMany({
where: { userId },
@@ -100,7 +110,7 @@ export async function getProjectById(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
const project = await prisma.aslScreeningProject.findFirst({
@@ -148,7 +158,7 @@ export async function updateProject(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
const updateData = request.body;
@@ -190,7 +200,7 @@ export async function deleteProject(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
// 验证项目归属

View File

@@ -6,6 +6,17 @@ import { FastifyRequest, FastifyReply } from 'fastify';
import { prisma } from '../../../config/database.js';
import { logger } from '../../../common/logging/index.js';
/**
* 获取用户ID从JWT Token中获取
*/
function getUserId(request: FastifyRequest): string {
const userId = (request as any).user?.userId;
if (!userId) {
throw new Error('User not authenticated');
}
return userId;
}
/**
* 获取筛选任务进度
* GET /api/v1/asl/projects/:projectId/screening-task
@@ -15,7 +26,7 @@ export async function getScreeningTask(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
// 验证项目归属
@@ -74,7 +85,7 @@ export async function getScreeningResults(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
const page = parseInt(request.query.page || '1', 10);
const pageSize = parseInt(request.query.pageSize || '50', 10);
@@ -175,7 +186,7 @@ export async function getScreeningResultDetail(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { resultId } = request.params;
const result = await prisma.aslScreeningResult.findUnique({
@@ -241,7 +252,7 @@ export async function reviewScreeningResult(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { resultId } = request.params;
const { decision, note } = request.body;
@@ -327,7 +338,7 @@ export async function getProjectStatistics(
reply: FastifyReply
) {
try {
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
const { projectId } = request.params;
// 1. 验证项目归属

View File

@@ -348,6 +348,9 @@ runTests().catch((error) => {

View File

@@ -327,6 +327,9 @@ Content-Type: application/json

View File

@@ -18,6 +18,17 @@ import { FulltextScreeningService } from '../services/FulltextScreeningService.j
// 初始化服务
const screeningService = new FulltextScreeningService();
/**
* 获取用户ID从JWT Token中获取
*/
function getUserId(request: FastifyRequest): string {
const userId = (request as any).user?.userId;
if (!userId) {
throw new Error('User not authenticated');
}
return userId;
}
// ==================== Zod验证Schema ====================
/**
@@ -79,7 +90,7 @@ export async function createTask(
const { projectId, literatureIds, modelA, modelB, promptVersion } = validated;
// 获取当前用户ID测试模式
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
logger.info('Creating fulltext screening task', {
projectId,
@@ -204,7 +215,7 @@ export async function getTaskProgress(
) {
try {
const { taskId } = request.params;
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
// 获取任务详情
const task = await prisma.aslFulltextScreeningTask.findFirst({
@@ -318,7 +329,7 @@ export async function getTaskResults(
) {
try {
const { taskId } = request.params;
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
// 参数验证
const validated = GetResultsQuerySchema.parse(request.query);
@@ -507,7 +518,7 @@ export async function updateDecision(
) {
try {
const { resultId } = request.params;
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
// 参数验证
const validated = UpdateDecisionSchema.parse(request.body);
@@ -589,7 +600,7 @@ export async function exportExcel(
) {
try {
const { taskId } = request.params;
const userId = (request as any).userId || 'asl-test-user-001';
const userId = getUserId(request);
// 验证任务权限
const task = await prisma.aslFulltextScreeningTask.findFirst({