修复系统概览数据不准确的查询。修复交叉评查意见列表的数量查询。优化全局消息提示的层级。优化提交意见进行局部更新。
This commit is contained in:
@@ -175,6 +175,7 @@ interface ReviewPointsListProps {
|
||||
scoringProposals?: ScoringProposal[];
|
||||
jwtToken?: string; // 添加JWT token参数
|
||||
userInfo?: UserInfo; // 添加用户信息参数
|
||||
onOpinionSubmitted?: (newProposal: ScoringProposal) => void; // 新增:意见提交成功后的回调
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -433,12 +434,14 @@ export function ReviewPointsList({
|
||||
onReviewPointSelect,
|
||||
scoringProposals = [],
|
||||
jwtToken,
|
||||
userInfo
|
||||
userInfo,
|
||||
onOpinionSubmitted
|
||||
}: ReviewPointsListProps) {
|
||||
// 状态管理
|
||||
const [searchText, setSearchText] = useState(''); // 搜索文本
|
||||
const [statusFilter, setStatusFilter] = useState<string | null>(null); // 状态过滤
|
||||
const [evaluationResultIds, setEvaluationResultIds] = useState<number[]>([]); // 评分提案的evaluation_result_id
|
||||
const [localScoringProposals, setLocalScoringProposals] = useState<ScoringProposal[]>(scoringProposals); // 本地状态管理scoringProposals
|
||||
const fetcher = useFetcher();
|
||||
|
||||
// 归一化 reviewPoints,确保每个点都有 id 字段
|
||||
@@ -452,17 +455,21 @@ export function ReviewPointsList({
|
||||
setNormalizedReviewPoints(norm);
|
||||
}, [reviewPoints]);
|
||||
|
||||
// 在组件中使用scoringProposals(这里只是简单使用以避免linter警告)
|
||||
// 将来可以用于显示相关的评分提案信息
|
||||
// 同步外部scoringProposals到本地状态
|
||||
useEffect(() => {
|
||||
if (scoringProposals && scoringProposals.length > 0) {
|
||||
// console.log('收到评分提案数据:', scoringProposals.length, '个提案');
|
||||
setLocalScoringProposals(scoringProposals);
|
||||
}, [scoringProposals]);
|
||||
|
||||
// 在组件中使用localScoringProposals
|
||||
useEffect(() => {
|
||||
if (localScoringProposals && localScoringProposals.length > 0) {
|
||||
// console.log('收到评分提案数据:', localScoringProposals.length, '个提案');
|
||||
// 获取提案的evaluation_result_id
|
||||
const evaluationResultIds = scoringProposals.map(proposal => Number(proposal.evaluation_result_id));
|
||||
const evaluationResultIds = localScoringProposals.map(proposal => Number(proposal.evaluation_result_id));
|
||||
setEvaluationResultIds(evaluationResultIds);
|
||||
// console.log('提案的evaluation_result_id:', evaluationResultIds);
|
||||
}
|
||||
}, [scoringProposals]);
|
||||
}, [localScoringProposals]);
|
||||
|
||||
// 提出意见模态框相关状态
|
||||
const [isOpinionModalOpen, setIsOpinionModalOpen] = useState(false);
|
||||
@@ -618,14 +625,14 @@ export function ReviewPointsList({
|
||||
* 打开意见列表模态框
|
||||
*/
|
||||
const handleOpenOpinionListModal = (reviewPoint: ReviewPoint) => {
|
||||
console.log('查看reviewPoint', reviewPoint);
|
||||
if (scoringProposals.length === 0) {
|
||||
// console.log('查看reviewPoint', reviewPoint);
|
||||
if (localScoringProposals.length === 0) {
|
||||
toastService.warning('当前文件尚未有人提出过意见');
|
||||
return;
|
||||
}
|
||||
setSelectedReviewPoint(reviewPoint);
|
||||
setIsOpinionListModalOpen(true);
|
||||
console.log('打开意见列表模态框');
|
||||
// console.log('打开意见列表模态框');
|
||||
// 直接传递reviewPoint的documentId,避免依赖状态更新
|
||||
loadOpinionListData(1, 10, reviewPoint.documentId);
|
||||
};
|
||||
@@ -714,14 +721,14 @@ export function ReviewPointsList({
|
||||
}
|
||||
|
||||
// 新增:详细打印每个校验条件
|
||||
console.log('校验前 selectedReviewPoint:', selectedReviewPoint);
|
||||
console.log('校验前 opinionForm:', opinionForm);
|
||||
console.log('校验前 userInfo:', userInfo);
|
||||
console.log('documentId:', selectedReviewPoint.documentId, 'isNaN:', isNaN(Number(selectedReviewPoint.documentId)), 'typeof:', typeof selectedReviewPoint.documentId);
|
||||
console.log('pointId:', selectedReviewPoint.pointId, 'isNaN:', isNaN(Number(selectedReviewPoint.pointId)), 'typeof:', typeof selectedReviewPoint.pointId);
|
||||
console.log('deductionScore:', opinionForm.deductionScore, 'typeof:', typeof opinionForm.deductionScore, 'isNaN:', isNaN(Number(opinionForm.deductionScore)));
|
||||
console.log('auditOpinion:', opinionForm.auditOpinion, 'trim:', String(opinionForm.auditOpinion).trim(), 'typeof:', typeof opinionForm.auditOpinion);
|
||||
console.log('user_id:', userInfo?.user_id, 'typeof:', typeof userInfo?.user_id);
|
||||
// console.log('校验前 selectedReviewPoint:', selectedReviewPoint);
|
||||
// console.log('校验前 opinionForm:', opinionForm);
|
||||
// console.log('校验前 userInfo:', userInfo);
|
||||
// console.log('documentId:', selectedReviewPoint.documentId, 'isNaN:', isNaN(Number(selectedReviewPoint.documentId)), 'typeof:', typeof selectedReviewPoint.documentId);
|
||||
// console.log('pointId:', selectedReviewPoint.pointId, 'isNaN:', isNaN(Number(selectedReviewPoint.pointId)), 'typeof:', typeof selectedReviewPoint.pointId);
|
||||
// console.log('deductionScore:', opinionForm.deductionScore, 'typeof:', typeof opinionForm.deductionScore, 'isNaN:', isNaN(Number(opinionForm.deductionScore)));
|
||||
// console.log('auditOpinion:', opinionForm.auditOpinion, 'trim:', String(opinionForm.auditOpinion).trim(), 'typeof:', typeof opinionForm.auditOpinion);
|
||||
// console.log('user_id:', userInfo?.user_id, 'typeof:', typeof userInfo?.user_id);
|
||||
|
||||
// 更严谨的校验逻辑
|
||||
if (
|
||||
@@ -741,12 +748,12 @@ export function ReviewPointsList({
|
||||
}
|
||||
|
||||
// 打印所有关键数据
|
||||
console.log('selectedReviewPoint:', selectedReviewPoint);
|
||||
console.log('opinionForm:', opinionForm);
|
||||
console.log('userInfo:', userInfo);
|
||||
// console.log('selectedReviewPoint:', selectedReviewPoint);
|
||||
// console.log('opinionForm:', opinionForm);
|
||||
// console.log('userInfo:', userInfo);
|
||||
|
||||
// 组装后端要求的字段名和内容
|
||||
const data: Record<string, any> = {
|
||||
const data = {
|
||||
document_id: Number(selectedReviewPoint.documentId),
|
||||
evaluation_point_id: Number(selectedReviewPoint.pointId),
|
||||
proposed_score: Number(opinionForm.deductionScore),
|
||||
@@ -759,10 +766,10 @@ export function ReviewPointsList({
|
||||
data.evaluation_result_id = Number(selectedReviewPoint.evaluationPointId);
|
||||
}
|
||||
// 打印最终请求体
|
||||
console.log('最终请求体:', data);
|
||||
// console.log('最终请求体:', data);
|
||||
// 用原生 fetch + application/json 提交
|
||||
try {
|
||||
const response = await fetch(`${API_BASE_URL.replace(/\/$/, '')}/admin/cross_review/proposals`, {
|
||||
const response = await fetch(`${API_BASE_URL.value.replace(/\/$/, '')}/admin/cross_review/proposals`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
@@ -773,6 +780,28 @@ export function ReviewPointsList({
|
||||
const result = await response.json();
|
||||
if (response.ok) {
|
||||
toastService.success('意见提交成功');
|
||||
|
||||
// 创建新的提案对象
|
||||
const newProposal: ScoringProposal = {
|
||||
id: result.id || Date.now(), // 使用返回的ID或时间戳作为临时ID
|
||||
evaluation_result_id: data.evaluation_result_id,
|
||||
proposer_id: data.proposer_id as number,
|
||||
proposed_score: data.proposed_score,
|
||||
reason: data.reason,
|
||||
status: 'pending', // 默认状态
|
||||
created_at: new Date().toISOString(),
|
||||
updated_at: new Date().toISOString(),
|
||||
document_id: data.document_id
|
||||
};
|
||||
|
||||
// 更新本地状态
|
||||
setLocalScoringProposals(prev => [...prev, newProposal]);
|
||||
|
||||
// 调用父组件回调(如果提供)
|
||||
if (onOpinionSubmitted) {
|
||||
onOpinionSubmitted(newProposal);
|
||||
}
|
||||
|
||||
handleCloseOpinionModal();
|
||||
} else {
|
||||
toastService.error(result.detail || '提交意见失败');
|
||||
@@ -2487,7 +2516,7 @@ export function ReviewPointsList({
|
||||
</button>
|
||||
<button
|
||||
className="px-4 py-2 bg-green-700 border border-transparent rounded-md text-sm font-medium text-white hover:bg-green-600 disabled:opacity-50"
|
||||
onClick={handleSubmitOpinion}
|
||||
onClick={() => handleSubmitOpinion()}
|
||||
disabled={isSubmittingOpinion}
|
||||
>
|
||||
{isSubmittingOpinion ? '提交中...' : '发起投票'}
|
||||
@@ -2652,7 +2681,7 @@ export function ReviewPointsList({
|
||||
{
|
||||
title: "投票人",
|
||||
key: "votes",
|
||||
width: "25%",
|
||||
width: "22%",
|
||||
align: "center" as const,
|
||||
render: (_: unknown, record: CrossCheckingOpinion) => {
|
||||
// 投票类型配置
|
||||
@@ -2707,9 +2736,9 @@ export function ReviewPointsList({
|
||||
{
|
||||
title: "意见发起人",
|
||||
key: "proposer",
|
||||
width: "4%",
|
||||
width: "8%",
|
||||
render: (_: unknown, record: CrossCheckingOpinion) => (
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="flex items-center justify-center text-left">
|
||||
<span
|
||||
className="px-1.5 py-0.5 rounded text-xs font-medium text-yellow-700 bg-yellow-100 border border-yellow-200 whitespace-nowrap overflow-hidden text-ellipsis max-w-[80px] transition-all hover:scale-[1.03] hover:shadow-sm"
|
||||
>
|
||||
@@ -2721,7 +2750,7 @@ export function ReviewPointsList({
|
||||
{
|
||||
title: "发起时间",
|
||||
key: "created_at",
|
||||
width: "18%",
|
||||
width: "12%",
|
||||
render: (_: unknown, record: CrossCheckingOpinion) => (
|
||||
<div className="text-sm text-left">{record.created_at}</div>
|
||||
)
|
||||
@@ -2729,7 +2758,7 @@ export function ReviewPointsList({
|
||||
{
|
||||
title: "投票状态",
|
||||
key: "opinion_status",
|
||||
width: "10%",
|
||||
width: "12%",
|
||||
render: (_: unknown, record: CrossCheckingOpinion) => {
|
||||
let label = '';
|
||||
let color = '';
|
||||
@@ -2754,7 +2783,7 @@ export function ReviewPointsList({
|
||||
{
|
||||
title: "操作",
|
||||
key: "operation",
|
||||
width: "18%",
|
||||
width: "auto",
|
||||
align: "center" as const,
|
||||
render: (_: unknown, record: CrossCheckingOpinion) => {
|
||||
const isPerforming = (action: string) => performingAction === `${record.proposal_id}-${action}`;
|
||||
@@ -2869,7 +2898,7 @@ function OpinionActions({ record, isPerforming, handleOpinionAction, userInfo }:
|
||||
</>
|
||||
)}
|
||||
{/* 仅当can_vote为false时显示撤销投票按钮 */}
|
||||
{!record.can_vote && (
|
||||
{!record.can_vote && !isProposer && (
|
||||
<Button
|
||||
type="default"
|
||||
className="bg-yellow-600 hover:bg-yellow-700 text-white min-w-[80px] h-14 text-base font-medium rounded-lg flex items-center justify-center whitespace-nowrap shadow-md hover:shadow-lg transition-all duration-200 px-4 py-3"
|
||||
|
||||
Reference in New Issue
Block a user