import { postgrestGet, postgrestPut } from "../postgrest-client"; /** * 从不同格式的 API 响应中提取数据 * @param responseData API 响应数据 * @returns 提取后的数据或 null */ function extractApiData(responseData: unknown): T | null { if (!responseData) return null; // 格式1: { code: number, msg: string, data: T } if (typeof responseData === 'object' && responseData !== null && 'code' in responseData && 'data' in responseData && (responseData as { data: unknown }).data) { return (responseData as { data: T }).data; } // 格式2: 直接是数据对象 return responseData as T; } /** * 提出意见的请求参数接口 */ export interface SubmitOpinionRequest { reviewPointResultId: string | number; documentId: string | number; evaluationPointId: number | null; // 必须是数字ID auditOpinion: string; deductionScore: number; } /** * 提出意见的响应接口 */ export interface SubmitOpinionResponse { success: boolean; message: string; data?: { id: string | number; created_at: string; }; } /** * 交叉评查意见数据接口 */ export interface CrossCheckingOpinion { proposal_id: string | number; evaluation_point_name: string; proposed_score: number; reason: string; proposer: string; votes: Array<{ voter: string; vote_type: string }>; agree_voters: string[]; disagree_voters: string[]; pending_voters: string[]; can_vote: boolean; problem_message: string; proposer_id: number; created_at: string; status: string; } /** * API响应格式 */ export interface ApiResponse { data?: T; error?: string; status?: number; } /** * 安全获取JWT token * @param jwtToken JWT token字符串 * @returns JWT token字符串 */ async function safeGetJWT(jwtToken?: string): Promise { return jwtToken || ''; } /** * 获取当前登录用户是否是发起人 * @param taskId 任务ID * @param userId 用户ID * @returns 是否是发起人 */ export async function findIsProposer(taskId: string | number, userId: number | undefined): Promise { // 通过postgrest的get请求去cross_examination_tasks表中进行查找assignee_id是否等于userId const response = await postgrestGet(`cross_examination_tasks`, { select: 'assigner_id', filter: { id: `eq.${taskId}` } }); if (response.error) { console.error('获取任务数据失败:', response.error); return false; } const data = extractApiData<{assigner_id: number}[]>(response.data); // console.log('data', data); if (data && data.length > 0) { return data[0].assigner_id === userId; } return false; } /** * 提交交叉评查意见 * @param opinionData 意见数据 * @param jwtToken JWT token * @returns 提交结果 */ export async function submitCrossCheckingOpinion( opinionData: SubmitOpinionRequest, jwtToken?: string, userInfo?: { user_id: number } ): Promise> { try { // 获取JWT token const token = await safeGetJWT(jwtToken); const requestData = { document_id: opinionData.documentId, evaluation_point_id: Number(opinionData.evaluationPointId), // 强制转数字 proposed_score: opinionData.deductionScore, reason: opinionData.auditOpinion, proposer_id: userInfo?.user_id || 1, evaluation_result_id: opinionData.reviewPointResultId }; const response = await fetch(`${API_BASE_URL}/admin/cross_review/proposals`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(requestData) }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || '提交失败'); } return { data: { success: true, message: '意见提交成功', data: data } }; } catch (error) { console.error('提交交叉评查意见失败:', error); return { error: error instanceof Error ? error.message : '提交意见失败', status: 500 }; } } /** * 获取交叉评查意见列表(支持分页) * @param documentId 文档ID * @param page 页码 * @param pageSize 每页大小 * @param userId 用户ID,可选,便于后端接口对接 * @param jwtToken JWT token * @returns 意见列表和总数 */ import { API_BASE_URL } from '../../config/api-config'; export async function getCrossCheckingOpinions( documentId: string | number, page: number = 1, pageSize: number = 10, userId?: number, // 可选,便于后端接口对接 jwtToken?: string // 改为jwtToken参数 ): Promise> { try { // 获取JWT token const token = await safeGetJWT(jwtToken); // 如果没传userId,默认用1 const realUserId = userId ?? 1; // 实际后端API调用,拼接API_BASE_URL const response = await fetch(`${API_BASE_URL}/admin/cross_review/proposals/document`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify({ user_id: realUserId, document_id: documentId, // 如果后端需要document_id可以加上 page, page_size: pageSize }) }); if (!response.ok) { throw new Error('获取意见列表失败'); } const data = await response.json(); console.log('最原始的返回data', data); // 处理新的数据结构,支持分页 const responseData = data.data || data; const pagination = data.pagination; // 定义后端返回的数据项类型 interface ProposalItem { proposal_id: string | number; evaluation_point_name: string; proposed_score: number; reason: string; proposer: string; votes?: Array<{ voter: string; vote_type: string }>; agree_voters?: string[]; disagree_voters?: string[]; pending_voters?: string[]; can_vote?: boolean; problem_message?: string; proposer_id: number; created_at: string; status: string; } // 适配后端返回结构,使用新字段 const opinions: CrossCheckingOpinion[] = Array.isArray(responseData) ? responseData.map((item: ProposalItem) => ({ proposal_id: item.proposal_id, evaluation_point_name: item.evaluation_point_name, proposed_score: item.proposed_score, reason: item.reason, proposer: item.proposer, votes: item.votes || [], agree_voters: item.agree_voters || [], disagree_voters: item.disagree_voters || [], pending_voters: item.pending_voters || [], can_vote: item.can_vote ?? false, problem_message: item.problem_message || '', proposer_id: item.proposer_id, created_at: item.created_at, status: item.status })) : []; return { data: { opinions, total: pagination?.total || opinions.length } }; } catch (error) { console.error('获取交叉评查意见失败:', error); return { error: error instanceof Error ? error.message : '获取意见列表失败', status: 500 }; } } /** * 意见操作类型 */ export type OpinionActionType = 'agree' | 'disagree' | 'withdraw_vote' | 'withdraw_opinion'; /** * 投票请求参数接口 */ export interface OpinionVoteCreate { vote_type: 'agree' | 'disagree'; } /** * 意见操作请求参数 */ export interface OpinionActionRequest { opinionId: string | number; action: OpinionActionType; } /** * 执行意见操作(赞同、反对、撤销投票、撤销意见) * @param actionData 操作数据 * @param jwtToken JWT token * @returns 操作结果 */ export async function performOpinionAction( actionData: OpinionActionRequest, jwtToken?: string, userInfo?: { user_id: number } ): Promise> { try { const token = await safeGetJWT(jwtToken); let message = ''; let endpoint = ''; let requestBody: Record = {}; switch (actionData.action) { case 'agree': message = '已赞同该意见'; endpoint = `${API_BASE_URL}/admin/cross_review/proposals/${actionData.opinionId}/votes`; requestBody = { vote_type: 'agree', voter_id: userInfo?.user_id }; break; case 'disagree': message = '已反对该意见'; endpoint = `${API_BASE_URL}/admin/cross_review/proposals/${actionData.opinionId}/votes`; requestBody = { vote_type: 'disagree', voter_id: userInfo?.user_id }; break; case 'withdraw_vote': message = '已撤销投票'; // 撤销投票的接口,根据实际API调整 endpoint = `${API_BASE_URL}/admin/cross_review/proposals/${actionData.opinionId}/votes`; requestBody = { vote_type: 'cancel', voter_id: userInfo?.user_id }; break; case 'withdraw_opinion': message = '已撤销意见'; // 撤销意见的接口,根据实际API调整 endpoint = `${API_BASE_URL}/admin/cross_review/proposals/${actionData.opinionId}`; requestBody = {}; break; default: throw new Error('无效的操作类型'); } const response = await fetch(endpoint, { method: actionData.action === 'withdraw_opinion' ? 'DELETE' : 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(requestBody) }); const data = await response.json(); console.log('返回的意见列表数据',data); if (!response.ok) { throw new Error(data.message || data.error || '操作失败'); } return { data: { success: true, message: message } }; } catch (error) { console.error('执行意见操作失败:', error); return { error: error instanceof Error ? error.message : '操作失败', status: 500 }; } } /** * 完成评查 * @param documentId 文档ID * @returns 完成评查结果 */ export async function confirmReviewResults( documentId: string | number ): Promise<{data?: unknown, error?: string, status?: number}> { try { // 通过postgrest的post请求去documents表中进行查找id等于documentId的数据,更新documents表的audit_status为1 const response = await postgrestPut(`documents`, { audit_status: 1 }, { id: documentId }); if(response.error) { return { error: response.error, status: response.status }; } const extractedData = extractApiData(response.data); if(!extractedData) { return { error: '更新文档状态失败', status: 500 }; } return { data: extractedData }; } catch (error) { console.error('完成评查失败:', error); return { error: error instanceof Error ? error.message : '完成评查失败', status: 500 }; } } // 点击完成评查按钮后,调用接口,检查文档下提案是否存在未投票用户 export async function checkProposalVotes( documentId: string | number, jwtToken?: string ): Promise<{data?: unknown, error?: string, status?: number}> { try { // 获取JWT token const token = await safeGetJWT(jwtToken); const requestData = { document_id: documentId }; const response = await fetch(`${API_BASE_URL}/admin/cross_review/proposals/document/check_pending_votes`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'Authorization': `Bearer ${token}` }, body: JSON.stringify(requestData) }); const data = await response.json(); if (!response.ok) { throw new Error(data.message || '检查失败'); } console.log("检查投票数据",data); return { data: { success: true, message: '检查成功', data: data } }; } catch (error) { console.error('检查失败:', error); return { error: error instanceof Error ? error.message : '检查失败', status: 500 }; } }