Merge branch 'Wren' into shiy-login

This commit is contained in:
2025-07-24 09:46:41 +08:00
6 changed files with 236 additions and 151 deletions
+2
View File
@@ -71,6 +71,8 @@ export async function loader({ request }: LoaderFunctionArgs) {
// 获取用户会话信息
const { getUserSession } = await import("~/api/login/auth.server");
const { userInfo, frontendJWT } = await getUserSession(request);
console.log('frontendJWT', frontendJWT);
// 获取任务列表和统计数据,传递用户信息和JWT
const [tasksResponse, statsResponse] = await Promise.all([
+54 -46
View File
@@ -14,13 +14,14 @@ import {
type CrossCheckingUploadedFile,
generateFileId,
formatFileSize,
batchUploadCrossCheckingFiles
batchUploadAndAssignCrossCheckingFiles
} from "~/api/cross-checking/cross-files-upload";
import {
getOrganizationTree,
convertToTreeData
} from "~/api/user";
import React from "react"; // Added for React.useState
import { API_BASE_URL } from '~/config/api-config';
export const meta: MetaFunction = () => {
return [
@@ -144,14 +145,15 @@ export const loader = async ({ request }: LoaderFunctionArgs) => {
* @param token JWT Token
* @returns 创建结果
*/
async function createCrossReviewTask(taskData: {
export async function createCrossReviewTask(taskData: {
documentIds: number[];
userIds: number[];
assignerId: number;
taskName: string;
docType: string;
}, token: string) {
try {
const response = await fetch('/admin/crossreview/tasks/assign', {
const response = await fetch(`${API_BASE_URL}/admin/cross_review/tasks/assign`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
@@ -161,7 +163,8 @@ async function createCrossReviewTask(taskData: {
document_ids: taskData.documentIds,
user_ids: taskData.userIds,
assigner_id: taskData.assignerId,
task_name: taskData.taskName
task_name: taskData.taskName,
doc_type: taskData.docType
})
});
@@ -207,7 +210,7 @@ export default function CrossCheckingUpload() {
type: '市局交叉评查',
});
// 步骤2状态
const [groupChecked, setGroupChecked] = useState<string[]>([]);
const [groupChecked, setGroupChecked] = useState<string[]>(userInfo?.user_id ? [`user_${userInfo.user_id}`] : []);
const [userSelectionState, setUserSelectionState] = useState<UserSelectionState>({
treeData: DEFAULT_TREE,
loading: false,
@@ -419,30 +422,9 @@ export default function CrossCheckingUpload() {
setIsUploading(true);
try {
// 第一步:上传文件
console.log("开始批量上传文件:", filesToUpload.length, "个,案卷类型:", caseType);
const uploadResult = await batchUploadCrossCheckingFiles(
filesToUpload.map(f => f.file),
caseType,
priority,
isTestDocument,
frontendJWT
);
// 第一步:上传文件并自动分配任务(新接口)
console.log("开始批量上传文件并分配任务:", filesToUpload.length, "个,案卷类型:", caseType);
const { successes, failures } = uploadResult;
if (failures.length > 0) {
toastService.error(`文件上传失败:${failures[0].error}`);
return;
}
// 第二步:创建交叉评查任务
console.log("文件上传成功,开始创建任务");
// 提取文档ID
const documentIds = successes.map(success => success.result.result?.id).filter(id => id !== undefined) as number[];
// 提取用户ID(从选中的组织架构中获取用户)
const userIds = groupChecked.filter(id => {
// 检查是否为用户ID(通常用户ID以特定前缀开头或有特定格式)
@@ -455,18 +437,31 @@ export default function CrossCheckingUpload() {
}
// 创建任务数据
const taskData = {
documentIds,
userIds,
assignerId: userInfo?.user_id || 1, // 使用当前用户ID作为分配者
taskName: taskInfo.name
const docTypeMap = {
[CaseType.ADMINISTRATIVE_PENALTY]: 'XZCF',
[CaseType.ADMINISTRATIVE_PERMIT]: 'XZXK'
};
console.log("创建任务数据:", taskData);
// 调用创建任务接口
await createCrossReviewTask(taskData, frontendJWT);
const uploadResult = await batchUploadAndAssignCrossCheckingFiles(
filesToUpload,
CASE_TYPE_TO_TYPE_ID[caseType],
priority,
documentNumber,
remark,
isTestDocument,
userIds,
taskInfo.name,
docTypeMap[caseType] || 'XZCF',
frontendJWT
);
const { successes, failures } = uploadResult;
if (failures.length > 0) {
toastService.error(`文件上传或任务分配失败:${failures[0].error}`);
return;
}
// 任务创建成功
toastService.success("交叉评查任务创建成功!");
messageService.success(
@@ -630,14 +625,28 @@ export default function CrossCheckingUpload() {
}
}
};
loadOrganizationData();
}, [currentStep]); // 只依赖 currentStep,避免无限循环
// 在 CrossCheckingUpload 组件内添加工具函数
function findUserNameById(tree: TreeNode[], userId: string): string | null {
for (const node of tree) {
if (node.value === userId && (node as { isUser?: boolean }).isUser) {
return node.label;
}
if (node.children) {
const found = findUserNameById(node.children, userId);
if (found) return found;
}
}
return null;
}
return (
<div className="min-h-screen bg-gray-50 py-8">
<div className="max-w-6xl mx-auto px-4">
{/* 步骤指示器 */
{/* 步骤指示器 */}
<div className="steps-indicator">
{STEPS.map((step) => (
<div
@@ -649,7 +658,6 @@ export default function CrossCheckingUpload() {
</div>
))}
</div>
}
{/* 步骤1:创建任务 */}
{currentStep === 1 && (
@@ -741,16 +749,16 @@ export default function CrossCheckingUpload() {
{groupChecked.length > 0 ? (
<div className="space-y-2 max-h-64 overflow-y-auto">
{groupChecked.map((member, index) => {
// 处理用户选择值,支持新的API格式
let displayName = member;
let displayName: string = member;
let displayOrg = '';
if (member.startsWith('user_')) {
// 用户选择,格式为 user_123
displayName = `用户ID: ${member.replace('user_', '')}`;
// 查找真实用户名
const userName = findUserNameById(userSelectionState.treeData, member) || member.replace('user_', '');
displayName = userName;
displayOrg = '用户';
} else {
// 组织选择,格式为 ou_id 或 ou_id-ou_id
// 组织
const parts = member.split('-');
displayName = parts[parts.length - 1];
displayOrg = parts.slice(0, -1).join(' - ') || '组织';