From 6261950356bf36634281607ff14a9243d2de5ce6 Mon Sep 17 00:00:00 2001 From: yorn <1057707203@qq.com> Date: Tue, 22 Apr 2025 20:49:18 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=97=B6=E9=97=B4=E8=8C=83?= =?UTF-8?q?=E5=9B=B4=E7=BB=84=E4=BB=B6=EF=BC=8C=E8=AF=84=E6=9F=A5=E8=AF=A6?= =?UTF-8?q?=E6=83=85=E5=88=9B=E5=BB=BA=E6=96=B0=E7=9A=84=E6=95=B0=E6=8D=AE?= =?UTF-8?q?=E7=BB=93=E6=9E=84=E6=9D=A5=E9=80=82=E9=85=8D=E6=96=B0=E7=9A=84?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/api/client.ts | 33 +- app/api/evaluation_points/reviews.ts | 14 +- app/api/evaluation_points/rules-files.ts | 73 ++-- app/api/postgrest-client.ts | 29 +- app/components/reviews/FilePreview.tsx | 40 +- app/components/reviews/ReviewPointsList.tsx | 429 +++++++++++++------- app/routes/files.upload.tsx | 8 +- app/routes/reviews.tsx | 12 +- app/routes/rule-groups._index.tsx | 5 +- app/routes/rule-groups.new.tsx | 218 ++++++++-- app/routes/rules-files.tsx | 112 +++-- app/routes/rules._index.tsx | 2 +- app/styles/pages/config-lists_index.css | 2 +- result.txt | Bin 0 -> 1358 bytes 14 files changed, 678 insertions(+), 299 deletions(-) create mode 100644 result.txt diff --git a/app/api/client.ts b/app/api/client.ts index 02c65b2..efc68d3 100644 --- a/app/api/client.ts +++ b/app/api/client.ts @@ -22,6 +22,29 @@ const API_BASE_URL = 'http://nas.7bm.co:3000'; // 是否使用模拟数据(开发环境使用) const USE_MOCK_DATA = false; // 设置为true使用模拟数据,避免API连接问题 +/** + * 将编码后的URL解码为可读格式 + * @param url 编码后的URL + * @returns 解码后的可读URL + */ +function decodeUrlForDisplay(url: string): string { + try { + // 首先解码整个URL + const decodedUrl = decodeURIComponent(url); + + // 如果URL中包含@符号作为前缀,则移除它 + if (decodedUrl.startsWith('@')) { + return decodedUrl.substring(1); + } + + return decodedUrl; + } catch (error) { + // 如果解码失败,返回原始URL + console.error('URL解码失败:', error); + return url; + } +} + /** * 构建完整的 API URL */ @@ -64,7 +87,7 @@ const fetchWithTimeout = async (url: string, options: RequestInit, timeout = 500 const id = setTimeout(() => controller.abort(), timeout); try { - console.log(`📦 API 端点: ${url}`); + console.log(`📦 client.ts->请求URL: ${decodeUrlForDisplay(url)}`); const response = await fetch(url, { ...options, signal: controller.signal @@ -73,7 +96,7 @@ const fetchWithTimeout = async (url: string, options: RequestInit, timeout = 500 return response; } catch (error) { clearTimeout(id); - console.error(`📦 API请求失败: ${error}`); + console.error(`📦 client.ts->请求请求失败: ${error}`); // 检查是否是网络连接问题 if (error instanceof TypeError && error.message.includes('fetch failed')) { @@ -171,11 +194,11 @@ export async function apiRequest( } } - console.log(`发送 ${options.method || 'GET'} 请求到: ${url}`); + console.log(`client.ts->发送 ${options.method || 'GET'} 请求到: ${decodeUrlForDisplay(url)}`); if (options.body) { - console.log(`请求体: ${options.body}`); + console.log(`client.ts->请求体: \n${options.body}`); } - + // 发送请求,10秒超时 const response = await fetchWithTimeout(url, { ...options, diff --git a/app/api/evaluation_points/reviews.ts b/app/api/evaluation_points/reviews.ts index 7f9ceae..a8b7257 100644 --- a/app/api/evaluation_points/reviews.ts +++ b/app/api/evaluation_points/reviews.ts @@ -251,7 +251,7 @@ export async function getReviewPoints(fileId: string) { } // 提取页码数组 - let contentPage: Record = {}; + let contentPage: Record = {}; // console.log('result-------', result.evaluated_results?.result); // console.log('datacontent-------', data); if (data && typeof data === 'object') { @@ -296,7 +296,17 @@ export async function getReviewPoints(fileId: string) { } } } - } catch (e) { + } + // // 4-22 更改数据结构:通过拿到的data数据(每一个key对应一个object),将object中的page提取出来 + // try{ + // const dataObj = data as Record; + // for (const key in dataObj) { + // if (Object.prototype.hasOwnProperty.call(dataObj, key)) { + // contentPage[key] = dataObj[key]; + // } + // } + // } + catch (e) { console.error('解析评查点data失败:', e); contentPage = {}; } diff --git a/app/api/evaluation_points/rules-files.ts b/app/api/evaluation_points/rules-files.ts index 699561b..fe0d8f5 100644 --- a/app/api/evaluation_points/rules-files.ts +++ b/app/api/evaluation_points/rules-files.ts @@ -1,18 +1,18 @@ import { postgrestGet, postgrestPut, type PostgrestParams } from '../postgrest-client'; -import dayjs from 'dayjs'; +// import dayjs from 'dayjs'; import { getDocumentTypes } from '../document-types/document-types'; import type { DocumentTypeUI } from '../document-types/document-types'; -import weekday from 'dayjs/plugin/weekday'; -import updateLocale from 'dayjs/plugin/updateLocale'; +// import weekday from 'dayjs/plugin/weekday'; +// import updateLocale from 'dayjs/plugin/updateLocale'; import { formatDate } from '../../utils'; -// 配置 dayjs -dayjs.extend(weekday); -dayjs.extend(updateLocale); -// 设置一周的第一天为周一 -dayjs.updateLocale('en', { - weekStart: 1 -}); +// // 配置 dayjs +// dayjs.extend(weekday); +// dayjs.extend(updateLocale); +// // 设置一周的第一天为周一 +// dayjs.updateLocale('en', { +// weekStart: 1 +// }); // 文档数据库表接口 export interface Document { @@ -79,7 +79,9 @@ export interface ReviewFileUI { export interface DocumentSearchParams { fileType?: string; // 文件类型ID reviewStatus?: string; // 评查状态 - dateRange?: string; // 日期范围 + // dateRange?: string; // 日期范围 + dateFrom?: string; // 开始日期 + dateTo?: string; // 结束日期 keyword?: string; // 搜索关键字 sortOrder?: string; // 排序方式 page?: number; // 当前页码 @@ -277,28 +279,41 @@ export async function getReviewFiles(searchParams: DocumentSearchParams = {}): P } // 处理日期范围筛选 - if (searchParams.dateRange) { - const now = dayjs(); - const today = now.startOf('day').format('YYYY-MM-DD HH:mm:ss'); - switch (searchParams.dateRange) { - case 'today': - filter['created_at'] = `gte.${today}`; - break; - case 'week': { - const weekStart = now.startOf('week').format('YYYY-MM-DD HH:mm:ss'); - filter['created_at'] = `gte.${weekStart}`; - break; - } - case 'month': { - const monthStart = now.startOf('month').format('YYYY-MM-DD HH:mm:ss'); - filter['created_at'] = `gte.${monthStart}`; - break; - } + if(searchParams.dateFrom){ + filter['created_at'] = `gte.${searchParams.dateFrom+ ' 00:00:00'}`; + } + + if(searchParams.dateTo){ + const dateToKey = searchParams.dateFrom ? 'and' : 'created_at'; + if(dateToKey === 'and'){ + delete filter['created_at']; + filter[dateToKey] = `(created_at.gte.${searchParams.dateFrom+' 00:00:00'},created_at.lte.${searchParams.dateTo+' 23:59:59'})`; + }else{ + filter['created_at'] = `lte.${searchParams.dateTo+' 23:59:59'}`; } } + // if (searchParams.dateRange) { + // const now = dayjs(); + // const today = now.startOf('day').format('YYYY-MM-DD HH:mm:ss'); + // switch (searchParams.dateRange) { + // case 'today': + // filter['created_at'] = `gte.${today}`; + // break; + // case 'week': { + // const weekStart = now.startOf('week').format('YYYY-MM-DD HH:mm:ss'); + // filter['created_at'] = `gte.${weekStart}`; + // break; + // } + // case 'month': { + // const monthStart = now.startOf('month').format('YYYY-MM-DD HH:mm:ss'); + // filter['created_at'] = `gte.${monthStart}`; + // break; + // } + // } + // } - // console.log('filter-----',filter); params.filter = filter; + console.log('params-----',params); // 发送API请求获取文档列表 const response = await postgrestGet('documents', params); diff --git a/app/api/postgrest-client.ts b/app/api/postgrest-client.ts index c1a560c..2ebfe4d 100644 --- a/app/api/postgrest-client.ts +++ b/app/api/postgrest-client.ts @@ -17,6 +17,29 @@ export interface PostgrestParams { headers?: Record; } +/** + * 将编码后的URL解码为可读格式 + * @param url 编码后的URL + * @returns 解码后的可读URL + */ +function decodeUrlForDisplay(url: string): string { + try { + // 首先解码整个URL + const decodedUrl = decodeURIComponent(url); + + // 如果URL中包含@符号作为前缀,则移除它 + if (decodedUrl.startsWith('@')) { + return decodedUrl.substring(1); + } + + return decodedUrl; + } catch (error) { + // 如果解码失败,返回原始URL + console.error('URL解码失败:', error); + return url; + } +} + /** * 打印 PostgREST 查询日志 * @param endpoint 端点 @@ -32,9 +55,9 @@ function logPostgrestQuery(endpoint: string, params?: QueryParams, method: strin // 确保 endpoint 格式正确 const normalizedEndpoint = endpoint.startsWith('/') ? endpoint.substring(1) : endpoint; - console.log('\n📦 PostgREST 查询日志 ========================'); + console.log('\n📦 PostgREST 查询日志 ======================start============='); console.log(`📦 HTTP 方法: ${method}`); - console.log(`📦 API 端点: ${baseUrl}/${normalizedEndpoint}`); + console.log(`📦 API 端点: ${decodeUrlForDisplay(`${baseUrl}/${normalizedEndpoint}`)}`); if (params && Object.keys(params).length > 0) { console.log('📦 查询参数:'); @@ -47,7 +70,7 @@ function logPostgrestQuery(endpoint: string, params?: QueryParams, method: strin }); } - console.log('=========================================\n'); + console.log('PostgREST 查询日志=============================end============\n'); } } diff --git a/app/components/reviews/FilePreview.tsx b/app/components/reviews/FilePreview.tsx index aff282d..f73c323 100644 --- a/app/components/reviews/FilePreview.tsx +++ b/app/components/reviews/FilePreview.tsx @@ -67,11 +67,11 @@ interface FileContent { interface FilePreviewProps { fileContent: FileContent; reviewPoints: ReviewPoint[]; - activeReviewPointId: string | null; + activeReviewPointResultId: string | null; targetPage?: number; // 新增目标页码参数 } -export function FilePreview({ fileContent, reviewPoints, activeReviewPointId, targetPage }: FilePreviewProps) { +export function FilePreview({ fileContent, reviewPoints, activeReviewPointResultId, targetPage }: FilePreviewProps) { const [zoomLevel, setZoomLevel] = useState(100); // const [highlightsVisible, setHighlightsVisible] = useState(true); const contentRef = useRef(null); @@ -119,7 +119,7 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointId, ta const prevTargetPageRef = useRef(undefined); useEffect(() => { // 如果有目标页码,并且与上次不同或activeReviewPointId变化了,则执行跳转 - if (targetPage && numPages && targetPage <= numPages && (targetPage !== prevTargetPageRef.current || activeReviewPointId)) { + if (targetPage && numPages && targetPage <= numPages && (targetPage !== prevTargetPageRef.current || activeReviewPointResultId)) { prevTargetPageRef.current = targetPage; let newTargetPage = targetPage; try { @@ -134,25 +134,25 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointId, ta const pageElement = document.getElementById(`page-${newTargetPage}`); if (pageElement) { - console.log(`跳转到第${newTargetPage}页,对应评查点结果ID: ${activeReviewPointId}`); + console.log(`跳转到第${newTargetPage}页,对应评查点结果ID: ${activeReviewPointResultId}`); pageElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); } } - }, [targetPage, numPages, fileContent, activeReviewPointId]); + }, [targetPage, numPages, fileContent, activeReviewPointResultId]); // 获取评查点对应的样式类 - const getHighlightClass = (status: string) => { - switch (status) { - case 'warning': - return 'warning'; - case 'error': - return 'error'; - case 'success': - return 'success'; - default: - return 'warning'; - } - }; + // const getHighlightClass = (status: string) => { + // switch (status) { + // case 'warning': + // return 'warning'; + // case 'error': + // return 'error'; + // case 'success': + // return 'success'; + // default: + // return 'warning'; + // } + // }; // 处理页码输入变化 const handlePageInputChange = (e: ChangeEvent) => { @@ -231,9 +231,9 @@ export function FilePreview({ fileContent, reviewPoints, activeReviewPointId, ta // 遍历每一页,生成对应的页面组件 for (let i = 1; i <= numPages; i++) { // 查找该页面上的评查点,基于position.section匹配页面ID - const pageReviewPoints = reviewPoints.filter(point => - point.position && point.position.section === `page-${i}` - ); + // const pageReviewPoints = reviewPoints.filter(point => + // point.position && point.position.section === `page-${i}` + // ); // 计算当前缩放级别下的页面容器样式 const zoomFactor = zoomLevel / 100; diff --git a/app/components/reviews/ReviewPointsList.tsx b/app/components/reviews/ReviewPointsList.tsx index 2c7885a..439ff03 100644 --- a/app/components/reviews/ReviewPointsList.tsx +++ b/app/components/reviews/ReviewPointsList.tsx @@ -34,7 +34,7 @@ export interface ReviewPoint { title: string; groupName: string; status: string; - content: Record; + content: Record; suggestion: string; needsHumanReview?: boolean; humanReviewNote?: string; @@ -49,7 +49,7 @@ export interface ReviewPoint { legalBasis?: { name?: string; content?: string; - articles?: Array; + articles?: Array; [key: string]: unknown; }; postAction?: string; @@ -68,17 +68,17 @@ interface Statistics { interface ReviewPointsListProps { reviewPoints: ReviewPoint[]; statistics: Statistics; - activeReviewPointId: string | null; + activeReviewPointResultId: string | null; onReviewPointSelect: (id: string, page?: number) => void; onStatusChange: (id: string, editAuditStatusId: string | number, status: string, message: string) => void; } -export function ReviewPointsList({ - reviewPoints, +export function ReviewPointsList({ + reviewPoints, statistics, - activeReviewPointId, + activeReviewPointResultId, onReviewPointSelect, - onStatusChange + onStatusChange }: ReviewPointsListProps) { // 状态管理 const [editingReviewPoint, setEditingReviewPoint] = useState(null); // 当前正在编辑的评查点ID @@ -86,23 +86,23 @@ export function ReviewPointsList({ const [statusFilter, setStatusFilter] = useState(null); // 状态过滤 const [suggestionTexts, setSuggestionTexts] = useState>({}); // 存储每个评查点的建议文本 - + // 添加重新审核意见的状态/ 用户输入的修改内容 / 用户提前写好的修改内容 const [manualReviewNotes, setManualReviewNotes] = useState>({}); - + // 初始化建议文本 useEffect(() => { // 将所有评查点的建议文本存储到状态中 const suggestions: Record = {}; - + reviewPoints.forEach(point => { suggestions[point.id] = point.suggestion || ''; }); setSuggestionTexts(suggestions); - + // 使用函数式更新,不再需要外部 manualReviewNotes 变量 setManualReviewNotes(prev => { - const notes = {...prev}; + const notes = { ...prev }; reviewPoints.forEach(point => { notes[point.id] = point.actionContent || ''; }); @@ -117,7 +117,7 @@ export function ReviewPointsList({ [reviewPointId]: text })); }; - + /** * 处理评查点审核操作 * @param reviewPointResultId 评查点结果ID @@ -137,7 +137,7 @@ export function ReviewPointsList({ // console.log('通过/不通过-------', reviewPointResultId, editAuditStatusId || '', action === 'approve' ? 'true' : 'false', message); onStatusChange(reviewPointResultId, editAuditStatusId || '', action === 'approve' ? 'true' : 'false', message); } - + // 将参数输出到控制台 console.log('评查点审核操作', { id: reviewPointResultId, @@ -146,35 +146,32 @@ export function ReviewPointsList({ content: message, status: action === 'approve' ? 'true' : (action === 'reject' ? 'false' : 'review') }); - + // 清除编辑状态 setEditingReviewPoint(null); }; - + /** * 过滤评查点 * 根据搜索文本和状态过滤条件筛选评查点 */ - const filteredReviewPoints = reviewPoints.filter(point => { + const filteredReviewPoints = reviewPoints.filter(point => { // 匹配搜索文本 - const matchesSearch = searchText === '' || + const matchesSearch = searchText === '' || point.pointName.toLowerCase().includes(searchText.toLowerCase()) || point.title.toLowerCase().includes(searchText.toLowerCase()) || point.groupName.toLowerCase().includes(searchText.toLowerCase()) || - (typeof point.content === 'object' && point.content !== null && - Object.values(point.content).some(value => - typeof value === 'string' && value.toLowerCase().includes(searchText.toLowerCase()) - )); - + JSON.stringify(point.content).toLowerCase().includes(searchText.toLowerCase()) + // 处理状态过滤 let matchesStatus = false; - + if (statusFilter === null) { // 未选择过滤条件时显示所有 matchesStatus = true; } else if (statusFilter === 'success') { // 过滤"通过"状态 - matchesStatus = point.result === true || (point.result === undefined && point.status === 'success'); + matchesStatus = point.result === true; } else if (statusFilter === 'warning') { // 过滤"警告"状态 matchesStatus = point.result === false && point.status === 'warning'; @@ -182,10 +179,10 @@ export function ReviewPointsList({ // 过滤"错误"状态 matchesStatus = point.result === false && point.status === 'error'; } - + return matchesSearch && matchesStatus; }); - + /** * 处理一键替换操作 * @param reviewPointId 评查点ID @@ -194,50 +191,50 @@ export function ReviewPointsList({ // 在实际应用中,这里应该调用API进行内容替换 // 模拟替换操作 alert(`将为评查点 ${reviewPointId} 执行一键替换操作`); - + // 更新评查点状态为成功 // onStatusChange(reviewPointId, 'success'); }; - + /** * 渲染评查统计信息 * 显示总计、通过、警告、错误数量 */ const renderStatistics = () => { // 确保传入的statistics存在,否则使用计算值 - const statsToUse = statistics || { + const statsToUse = statistics || { total: reviewPoints.length, success: 0, warning: 0, error: 0, score: 0 }; - + // 计算各个状态的评查点数量 const successCount = reviewPoints.filter( point => point.result === true || (point.result === undefined && point.status === 'success') ).length; - + const warningCount = reviewPoints.filter( point => point.result === false && point.status === 'warning' ).length; - + const errorCount = reviewPoints.filter( point => point.result === false && point.status === 'error' ).length; - + // 如果没有计算值,则使用传入的统计值 const totalToShow = statsToUse.total === 0 ? reviewPoints.length : statsToUse.total; const successToShow = successCount || statsToUse.success; const warningToShow = warningCount || statsToUse.warning; const errorToShow = errorCount || statsToUse.error; - + return (
{/* 总计数量 */}
-
); }; - + /** * 渲染搜索框 * 用于按文本搜索评查点 @@ -312,7 +309,7 @@ export function ReviewPointsList({ /> {searchText && ( -
); }; - + /** * 渲染评查点状态标签 * @param status 状态文本 @@ -339,7 +336,7 @@ export function ReviewPointsList({ ); } - + // 当result为false时,根据status决定显示警告还是错误 if (result === false) { if (status === 'warning') { @@ -356,7 +353,7 @@ export function ReviewPointsList({ ); } } - + // 兼容旧版逻辑,当没有result时,仍按status判断 switch (status) { case 'success': @@ -391,7 +388,7 @@ export function ReviewPointsList({ ); } }; - + /** * 渲染人工审核标记 * @param reviewPoint 评查点 @@ -407,13 +404,14 @@ export function ReviewPointsList({ } return null; }; - + /** * 渲染人工审核注释 * @param reviewPoint 评查点 * @returns 人工审核注释组件 */ const renderHumanReviewNote = (reviewPoint: ReviewPoint) => { + // 目前needsHumanReview和humanReviewNote都为空,所以不显示 if (reviewPoint.needsHumanReview && reviewPoint.humanReviewNote) { return (
@@ -428,11 +426,64 @@ export function ReviewPointsList({ } return null; }; - + + /** + * 渲染评查点主要内容 + * @param reviewPoint 评查点 + * @returns 评查点主要内容组件 + */ + const renderContent = (reviewPoint: ReviewPoint) => { + return ( + <> + {/* 修改评查结果的结构之后,显示新的结构 */} + {Object.entries(reviewPoint.content).map(([key, value], index) => ( +
{ + e.stopPropagation(); + console.log(`通过:单独点击${key}----`, reviewPoint); + // 检查value中的page属性是否存在 + if (value && typeof value === 'object' && value.page) { + // 获取当前 key 对应的第一个页码并跳转 + console.log(`通过:单独点击${key}----页码---`, value.page); + + onReviewPointSelect(reviewPoint.id, value.page); + } else { + console.log(`通过:单独点击${key}--------没有对应页码`); + } + }} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + if (value && typeof value === 'object' && value.page) { + onReviewPointSelect(reviewPoint.id, value.page); + } else { + console.log(`通过:单独点击${key}--------没有对应页码`); + } + } + }} + role="button" + tabIndex={0} + aria-label={`查看${key}内容详情`} + > +
+ {key} + + {value ? '' : '缺失'} + +
+
+ ))} + + ); + }; + + /** * 渲染评查点内容与建议 * @param reviewPoint 评查点 - * @returns 评查点内容组件 + * @returns 评查点内容与建议组件 */ const renderReviewPointContent = (reviewPoint: ReviewPoint) => { @@ -446,8 +497,8 @@ export function ReviewPointsList({ // 如果当前评查点不处于编辑状态,只显示简单信息 if (editingReviewPoint !== reviewPoint.id) { // 根据result和status决定渲染哪种样式 - if (reviewPoint.result === true ){ - // 已通过的评查点只显示基本信息和人工审核注释 delete + if (reviewPoint.result === true) { + // 已通过的评查点只显示基本信息和人工审核注释 delete TODO // if (reviewPoint.needsHumanReview && reviewPoint.humanReviewNote) { // return ( //
@@ -476,56 +527,115 @@ export function ReviewPointsList({ }; return ( -
- {reviewPoint.suggestion && ( -
-
- -

{reviewPoint.suggestion}

-
-
+ <> + {checkContentPage(reviewPoint).pageIndex === 0 && ( +

该评查点无法找到索引内容,无法自动定位到对应页面。

)} - - {/* 额外的文本输入框区域 */} -
- -
- -
- {reviewPoint.editAuditStatus === 0 ? ( -
- - +
+ {reviewPoint.suggestion && ( +
+
+ +

{reviewPoint.suggestion}

+
- ) : ( - )} + + {/* 评查点内容显示区域 */} + {reviewPoint.content && Object.entries(reviewPoint.content).length > 0 && ( +
+ {/* 修改评查结果的结构之前,先显示旧的结构 */} + {Object.entries(reviewPoint.content).map(([key, value], index) => ( +
{ + // 阻止事件冒泡,防止触发父元素的点击事件 + e.stopPropagation(); + + console.log(`通过:单独点击${key}----`, reviewPoint); + // 检查评查点是否有 contentPage 以及当前 key 对应的页码数组 + if (reviewPoint.contentPage && reviewPoint.contentPage[key] && reviewPoint.contentPage[key].length > 0) { + // 获取当前 key 对应的第一个页码并跳转 + console.log(`通过:单独点击${key}----页码---`, reviewPoint.contentPage[key][0]); + + onReviewPointSelect(reviewPoint.id, reviewPoint.contentPage[key][0]); + } else { + console.log(`通过:单独点击${key}--------没有对应页码`); + } + }} + onKeyDown={(e) => { + if (e.key === 'Enter' || e.key === ' ') { + e.preventDefault(); + if (reviewPoint.contentPage && reviewPoint.contentPage[key] && reviewPoint.contentPage[key].length > 0) { + onReviewPointSelect(reviewPoint.id, reviewPoint.contentPage[key][0]); + } else { + console.log(`通过:单独点击${key}--------没有对应页码`); + } + } + }} + role="button" + tabIndex={0} + aria-label={`查看${key}内容详情`} + > + {/* 使用flex布局使key和状态标签左右对齐 */} +
+ {key} + + {value ? '' : '缺失'} + +
+

{value || (value === '' ? 占位符 : '')}

+
+ ))} + {/* 修改评查结果的结构之后,显示新的结构 */} + {/* {renderContent(reviewPoint)} */} +
+ )} + + + + {/* 额外的文本输入框区域 */} +
+ +
+ +
+ {reviewPoint.editAuditStatus === 0 ? ( +
+ + +
+ ) : ( + + )} +
-
+ ); } - + // 处理 result=true 且 postAction!=manual 的情况 return ( <> @@ -534,20 +644,21 @@ export function ReviewPointsList({ )}
+ {/* 修改评查结果的结构之前,先显示旧的结构 */} {Object.entries(reviewPoint.content).map(([key, value], index) => ( -
{ // 阻止事件冒泡,防止触发父元素的点击事件 e.stopPropagation(); - - console.log(`通过:单独点击${key}----`,reviewPoint); + + console.log(`通过:单独点击${key}----`, reviewPoint); // 检查评查点是否有 contentPage 以及当前 key 对应的页码数组 if (reviewPoint.contentPage && reviewPoint.contentPage[key] && reviewPoint.contentPage[key].length > 0) { // 获取当前 key 对应的第一个页码并跳转 - console.log(`通过:单独点击${key}----页码---`,reviewPoint.contentPage[key][0]); - + console.log(`通过:单独点击${key}----页码---`, reviewPoint.contentPage[key][0]); + onReviewPointSelect(reviewPoint.id, reviewPoint.contentPage[key][0]); } else { console.log(`通过:单独点击${key}--------没有对应页码`); @@ -570,48 +681,47 @@ export function ReviewPointsList({ {/* 使用flex布局使key和状态标签左右对齐 */}
{key} - + {value ? '' : '缺失'}

{value || (value === '' ? 占位符 : '')}

))} + {/* 修改评查结果的结构之后,显示新的结构 */} + {/* {renderContent(reviewPoint)} */}
); } - + // 非通过状态,显示内容和修改建议 const isErrorStatus = reviewPoint.result === false && reviewPoint.status === 'error'; - - + + return (
{/* 没有索引内容提示 */} - {reviewPoint.contentPage && - checkContentPage(reviewPoint).pageIndex === 0 && ( - //
-

该评查点无法找到索引内容,无法自动定位到对应页面。

- //
+ {checkContentPage(reviewPoint).pageIndex === 0 && ( +

该评查点无法找到索引内容,无法自动定位到对应页面。

)} {/* 建议内容显示区域 */} {reviewPoint.suggestion && ( -
-
- -

{reviewPoint.suggestion}

-
+
+
+ +

{reviewPoint.suggestion}

+
)} - {/* 法律依据内容 */} - {reviewPoint.legalBasis && (typeof reviewPoint.legalBasis === 'object') && ( - (reviewPoint.legalBasis.name || reviewPoint.legalBasis.content || + {/* 法律依据内容 */} + {reviewPoint.legalBasis && (typeof reviewPoint.legalBasis === 'object') && ( + (reviewPoint.legalBasis.name || reviewPoint.legalBasis.content || (reviewPoint.legalBasis.articles && Array.isArray(reviewPoint.legalBasis.articles) && reviewPoint.legalBasis.articles.length > 0)) && (
@@ -629,10 +739,10 @@ export function ReviewPointsList({
    {reviewPoint.legalBasis.articles.map((item, index) => (
  • - {typeof item === 'string' ? item : - typeof item === 'object' && item !== null ? - (item.name ? `${item.name}: ${item.content || ''}` : - item.content || JSON.stringify(item)) : + {typeof item === 'string' ? item : + typeof item === 'object' && item !== null ? + (item.name ? `${item.name}: ${item.content || ''}` : + item.content || JSON.stringify(item)) : String(item)}
  • ))} @@ -649,20 +759,21 @@ export function ReviewPointsList({ {/* 内容显示区域 */}
    + {/* 修改评查结果的结构之前,先显示旧的结构 */} {Object.entries(reviewPoint.content).map(([key, value], index) => ( -
    { // 阻止事件冒泡,防止触发父元素的点击事件 e.stopPropagation(); - - console.log(`非通过:单独点击${key}----`,reviewPoint); + + console.log(`非通过:单独点击${key}----`, reviewPoint); // 检查评查点是否有 contentPage 以及当前 key 对应的页码数组 if (reviewPoint.contentPage && reviewPoint.contentPage[key] && reviewPoint.contentPage[key].length > 0) { // 获取当前 key 对应的第一个页码并跳转 - console.log(`非通过:单独点击${key}----页码---`,reviewPoint.contentPage[key][0]); - + console.log(`非通过:单独点击${key}----页码---`, reviewPoint.contentPage[key][0]); + onReviewPointSelect(reviewPoint.id, reviewPoint.contentPage[key][0]); } else { // 如果没有对应页码,弹出提示 @@ -695,6 +806,8 @@ export function ReviewPointsList({

    {value || (value === '' ? 占位符 : '')}

    ))} + {/* 修改评查结果的结构之后,显示新的结构 */} + {/* {renderContent(reviewPoint)} */}
    @@ -702,7 +815,7 @@ export function ReviewPointsList({ {/* 建议修改区域 */} {/* {((reviewPoint.postAction === 'manual') || (reviewPoint.content !== null && Object.keys(reviewPoint.content).length > 0)) && ( */} - {(reviewPoint.postAction === 'manual') && ( + {(reviewPoint.postAction === 'manual') && (
    {reviewPoint.postAction === 'manual' ? "审核意见:" : "建议修改为:"} @@ -723,18 +836,18 @@ export function ReviewPointsList({
    {/* 一键替换按钮 - 只有非人工审核的点或未通过的人工审核点才显示 */} {(reviewPoint.postAction !== 'manual') && ( - )} - + {/* 人工审核按钮 */} {reviewPoint.editAuditStatus === 0 ? (
    - -
    ) : (
    -
    ); } - + }; - + /** * 渲染无匹配结果提示 * 当过滤后没有评查点时显示 @@ -785,7 +898,7 @@ export function ReviewPointsList({

    没有找到匹配的评查点

    请尝试不同的搜索词或清除筛选条件

    {(searchText || statusFilter) && ( -
    ); }; - + // 处理评查点点击事件 const handleReviewPointClick = (id: string) => { // 找到被点击的评查点 const reviewPoint = reviewPoints.find(result => result.id === id); - + // 如果评查点存在 if (reviewPoint) { // 使用checkContentPage方法获取页码和key const { pageIndex, key } = checkContentPage(reviewPoint); - + // 如果有有效页码,传递ID和页码 if (pageIndex > 0) { console.log(`跳转到页面 ${pageIndex},对应内容 ${key || '未知'}`); onReviewPointSelect(id, pageIndex); return; } - + // 没有有效页码,只传递ID onReviewPointSelect(id); console.log(`没有有效页码---评查点ID:${reviewPoint.pointId},评查点结果ID:${id}`); @@ -825,17 +938,17 @@ export function ReviewPointsList({ console.log(`没有找到评查点---评查点结果ID:${id}`); } }; - + // 检查评查点的contentPage const checkContentPage = (reviewPoint: ReviewPoint): { pageIndex: number, key?: string, id: string } => { // 返回对象初始化 const result = { pageIndex: 0, id: reviewPoint.id }; - + // 如果contentPage不存在或是空对象,返回默认值 if (!reviewPoint.contentPage || Object.keys(reviewPoint.contentPage).length === 0) { return result; } - + // 遍历contentPage中的每个key for (const key of Object.keys(reviewPoint.contentPage)) { const pageArr = reviewPoint.contentPage[key]; @@ -849,11 +962,11 @@ export function ReviewPointsList({ }; } } - + // 如果遍历完所有key都没找到有效页码,返回默认值 return result; }; - + // 组件主渲染函数 return (
    @@ -862,20 +975,20 @@ export function ReviewPointsList({ 评查结果
    - + {/* 评查统计 */} {renderStatistics()} - + {/* 搜索框 */} {renderSearchBar()} - + {/* 评查点列表 */}
    {filteredReviewPoints.length > 0 ? ( filteredReviewPoints.map(reviewPoint => ( -
    handleReviewPointClick(reviewPoint.id)} onKeyDown={(e) => { if (e.key === 'Enter') { @@ -888,23 +1001,23 @@ export function ReviewPointsList({ > {/* 评查点标题和状态 */} {/* 评查点名称 pointName*/} -
    {'评查点名称:'+reviewPoint.pointName}
    +
    {'评查点名称:' + reviewPoint.pointName}
    -
    {reviewPoint.title}
    +
    {reviewPoint.title}
    {/* 评查点所属分组 */} -
    +
    {reviewPoint.groupName}
    -
    +
    {renderStatusBadge(reviewPoint.status, reviewPoint.result)} {renderHumanReviewBadge(reviewPoint)}
    - + {/* 人工审核注释 */} {renderHumanReviewNote(reviewPoint)} - + {/* 评查点内容和操作 */} {renderReviewPointContent(reviewPoint)}
    diff --git a/app/routes/files.upload.tsx b/app/routes/files.upload.tsx index 360eebb..3bcad90 100644 --- a/app/routes/files.upload.tsx +++ b/app/routes/files.upload.tsx @@ -9,6 +9,7 @@ import { FileProgress} from "~/components/ui/FileProgress"; import { ProcessingSteps, Step } from "~/components/ui/ProcessingSteps"; import uploadStyles from "~/styles/pages/files_upload.css?url"; import { messageService } from "~/components/ui/MessageModal"; +import { toastService } from "~/components/ui/Toast"; import { getTodayDocuments, getDocumentTypes, @@ -561,7 +562,7 @@ export default function FilesUpload() { } // 显示错误提示 - messageService.error('文件上传失败:只能上传pdf文件。', { + messageService.error(`文件上传失败:${error instanceof Error ? error.message : '未知错误'}`, { title: '文件上传失败', onConfirm: () => { resetUpload(); @@ -815,11 +816,12 @@ export default function FilesUpload() { const response = await updateDocumentAuditStatus(record.id.toString(), 2); if (response.error) { console.error('更新文件审核状态失败:', response.error); - alert('更新文件审核状态失败:' + (response.error || '未知错误')); + toastService.error('更新文件审核状态失败:' + (response.error || '未知错误')); } + } catch (error) { console.error('更新文件审核状态时出错:', error); - alert('更新文件审核状态时出错:' + (error instanceof Error ? error.message : '未知错误')); + toastService.error('更新文件审核状态时出错:' + (error instanceof Error ? error.message : '未知错误')); } } navigate(`/reviews?id=${record.id}&previousRoute=filesUpload`); diff --git a/app/routes/reviews.tsx b/app/routes/reviews.tsx index 8a52675..cf150d2 100644 --- a/app/routes/reviews.tsx +++ b/app/routes/reviews.tsx @@ -240,7 +240,7 @@ export default function ReviewDetails() { const [isLoading, setIsLoading] = useState(false); // 已经通过loader加载了数据,不需要再显示加载状态 const [activeTab, setActiveTab] = useState('preview'); // 'preview', 'analysis', 'fileinfo' const [reviewData, setReviewData] = useState(null); - const [activeReviewPointId, setActiveReviewPointId] = useState(null); + const [activeReviewPointResultId, setActiveReviewPointResultId] = useState(null); const [targetPage, setTargetPage] = useState(undefined); // 模拟获取评查数据 @@ -285,16 +285,16 @@ export default function ReviewDetails() { const handleReviewPointSelect = (reviewPointId: string, page?: number) => { // 如果点击的是相同的评查点,但有page参数,先重置targetPage以确保useEffect能够触发 - if (reviewPointId === activeReviewPointId && page) { + if (reviewPointId === activeReviewPointResultId && page) { setTargetPage(undefined); // 使用setTimeout确保状态更新后再设置新的targetPage setTimeout(() => { - setActiveReviewPointId(reviewPointId); + setActiveReviewPointResultId(reviewPointId); setTargetPage(page); }, 0); } else { // 正常设置activeReviewPointId和targetPage - setActiveReviewPointId(reviewPointId); + setActiveReviewPointResultId(reviewPointId); setTargetPage(page); } }; @@ -483,7 +483,7 @@ export default function ReviewDetails() {
    @@ -493,7 +493,7 @@ export default function ReviewDetails() { diff --git a/app/routes/rule-groups._index.tsx b/app/routes/rule-groups._index.tsx index bebda44..25bc48b 100644 --- a/app/routes/rule-groups._index.tsx +++ b/app/routes/rule-groups._index.tsx @@ -7,7 +7,7 @@ import { Button } from "~/components/ui/Button"; import { StatusDot } from "~/components/ui/StatusDot"; import { Table } from "~/components/ui/Table"; import { FilterPanel, FilterSelect, SearchFilter } from "~/components/ui/FilterPanel"; -import { Pagination } from "~/components/ui/Pagination"; +// import { Pagination } from "~/components/ui/Pagination"; import { getRuleGroups, getChildGroups, type RuleGroup, deleteRuleGroup } from "~/api/evaluation_points/rule-groups"; export function links() { @@ -539,7 +539,8 @@ export default function RuleGroupsIndex() { ]; return ( -
    + //
    +
    {/* 页面头部 */}

    评查点分组管理 diff --git a/app/routes/rule-groups.new.tsx b/app/routes/rule-groups.new.tsx index cc61991..f2df006 100644 --- a/app/routes/rule-groups.new.tsx +++ b/app/routes/rule-groups.new.tsx @@ -1,9 +1,10 @@ // app/routes/rule-groups.new.tsx -import { redirect, json, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction } from "@remix-run/node"; +import { redirect, type ActionFunctionArgs, type LoaderFunctionArgs, type MetaFunction } from "@remix-run/node"; import { useLoaderData, useActionData, useNavigation, Form } from "@remix-run/react"; -import { useEffect, useState } from "react"; +import { useEffect, useState, useRef } from "react"; import { Button } from "~/components/ui/Button"; import { Card } from "~/components/ui/Card"; +import { toastService } from "~/components/ui/Toast"; import ruleGroupsNewStyles from "~/styles/pages/rule-groups_new.css?url"; import { getRuleGroups, @@ -199,7 +200,7 @@ export async function action({ request }: ActionFunctionArgs) { // 处理API响应 if (response.error) { console.error("保存分组失败:", response.error); - return json({ + return Response.json({ success: false, errors: { general: response.error @@ -209,10 +210,11 @@ export async function action({ request }: ActionFunctionArgs) { } // 保存成功,重定向到列表页 + toastService.success("保存成功"); return redirect("/rule-groups"); } catch (error) { console.error("保存分组失败:", error); - return json({ + return Response.json({ success: false, errors: { general: error instanceof Error ? error.message : "保存分组失败,请稍后重试" @@ -230,31 +232,162 @@ export default function RuleGroupNew() { const navigation = useNavigation(); const isSubmitting = navigation.state === "submitting"; - // 表单状态 - const [groupType, setGroupType] = useState<"primary" | "secondary">("primary"); - const [showParentSelect, setShowParentSelect] = useState(false); - // 解构数据 const { group, parentGroups, isEdit, error } = data; - // 初始化表单状态 + // 表单状态管理 - 使用受控组件 + const [formValues, setFormValues] = useState<{ + groupType: "primary" | "secondary"; + name: string; + code: string; + parentId: string; + description: string; + status: string; + }>({ + groupType: group?.parentId ? "secondary" : "primary", + name: group?.name || "", + code: group?.code || "", + parentId: group?.parentId || "", + description: group?.description || "", + status: group?.status || "active", + }); + + // 表单验证错误状态 + const [formErrors, setFormErrors] = useState<{ + name?: string; + code?: string; + parentId?: string; + general?: string; + }>({}); + + // 表单引用 + const formRef = useRef(null); + + // 字段是否被触摸过(用于确定何时显示错误) + const [touchedFields, setTouchedFields] = useState<{ + name: boolean; + code: boolean; + parentId: boolean; + }>({ + name: false, + code: false, + parentId: false + }); + + // 从 actionData 初始化表单错误 + useEffect(() => { + if (actionData?.errors) { + setFormErrors(actionData.errors); + } + }, [actionData]); + + // 根据加载的组数据初始化表单 useEffect(() => { if (group) { - if (group.parentId) { - setGroupType("secondary"); - setShowParentSelect(true); - } else { - setGroupType("primary"); - setShowParentSelect(false); - } + setFormValues({ + groupType: group.parentId ? "secondary" : "primary", + name: group.name, + code: group.code, + parentId: group.parentId || "", + description: group.description || "", + status: group.status + }); } }, [group]); - // 处理分组类型变更 + // 验证表单字段 + const validateField = (field: string, value: string) => { + switch (field) { + case 'name': + return value.trim() === "" ? "分组名称不能为空" : ""; + case 'code': + if (value.trim() === "") { + return "分组编码不能为空"; + } else if (!/^[a-zA-Z0-9-_]+$/.test(value)) { + return "分组编码只能包含字母、数字、连字符和下划线"; + } + return ""; + case 'parentId': + return formValues.groupType === "secondary" && value.trim() === "" + ? "请选择上级分组" + : ""; + default: + return ""; + } + }; + + // 处理字段改变 + const handleChange = (e: React.ChangeEvent) => { + const { name, value } = e.target; + + setFormValues(prev => ({ + ...prev, + [name]: value + })); + + // 标记字段为已触摸 + if (['name', 'code', 'parentId'].includes(name)) { + setTouchedFields(prev => ({ + ...prev, + [name]: true + })); + } + + // 实时验证 + const error = validateField(name, value); + setFormErrors(prev => ({ + ...prev, + [name]: error + })); + }; + + // 处理分组类型更改 const handleGroupTypeChange = (e: React.ChangeEvent) => { const value = e.target.value as "primary" | "secondary"; - setGroupType(value); - setShowParentSelect(value === "secondary"); + + setFormValues(prev => ({ + ...prev, + groupType: value + })); + + // 如果切换为一级分组,清除父分组错误 + if (value === "primary") { + setFormErrors(prev => ({ + ...prev, + parentId: "" + })); + } else if (value === "secondary" && touchedFields.parentId) { + // 如果切换为二级分组,且父分组字段已被触摸,重新验证 + const error = validateField('parentId', formValues.parentId); + setFormErrors(prev => ({ + ...prev, + parentId: error + })); + } + }; + + // 处理表单提交前验证 + const handleBeforeSubmit = (e: React.FormEvent) => { + // 标记所有字段为已触摸 + setTouchedFields({ + name: true, + code: true, + parentId: true + }); + + // 验证所有字段 + const errors = { + name: validateField('name', formValues.name), + code: validateField('code', formValues.code), + parentId: validateField('parentId', formValues.parentId) + }; + + setFormErrors(errors); + + // 如果有错误,阻止提交 + if (errors.name || errors.code || (formValues.groupType === "secondary" && errors.parentId)) { + e.preventDefault(); + } }; // 如果加载数据时出错,显示错误信息 @@ -304,15 +437,15 @@ export default function RuleGroupNew() {

    {/* 错误提示 */} - {actionData?.errors?.general && ( + {formErrors.general && (
    - {actionData.errors.general} + {formErrors.general}
    )} {/* 表单 */} -
    + {/* 如果是编辑模式,添加ID */} {group?.id && } @@ -336,7 +469,7 @@ export default function RuleGroupNew() { name="groupType" className="radio-input" value="primary" - checked={groupType === "primary"} + checked={formValues.groupType === "primary"} onChange={handleGroupTypeChange} /> 一级分组 @@ -348,7 +481,7 @@ export default function RuleGroupNew() { name="groupType" className="radio-input" value="secondary" - checked={groupType === "secondary"} + checked={formValues.groupType === "secondary"} onChange={handleGroupTypeChange} /> 二级分组 @@ -358,7 +491,7 @@ export default function RuleGroupNew() {
    {/* 上级分组选择 */} - {showParentSelect && ( + {formValues.groupType === "secondary" && (
    @@ -396,12 +530,13 @@ export default function RuleGroupNew() { type="text" id="code" name="code" - className={`form-input ${actionData?.errors?.code ? 'error' : ''}`} - defaultValue={group?.code || actionData?.values?.code || ""} + className={`form-input ${touchedFields.code && formErrors.code ? 'error' : ''}`} + value={formValues.code} + onChange={handleChange} placeholder="请输入分组编码,如contract-base" /> - {actionData?.errors?.code && ( -
    {actionData.errors.code}
    + {touchedFields.code && formErrors.code && ( +
    {formErrors.code}
    )}
    编码只能包含字母、数字、连字符和下划线,且必须唯一
    @@ -415,12 +550,13 @@ export default function RuleGroupNew() { type="text" id="name" name="name" - className={`form-input ${actionData?.errors?.name ? 'error' : ''}`} - defaultValue={group?.name || actionData?.values?.name || ""} + className={`form-input ${touchedFields.name && formErrors.name ? 'error' : ''}`} + value={formValues.name} + onChange={handleChange} placeholder="请输入分组名称,如合同基本要素检查" /> - {actionData?.errors?.name && ( -
    {actionData.errors.name}
    + {touchedFields.name && formErrors.name && ( +
    {formErrors.name}
    )}
    请使用简洁明了的名称,不超过30个字符
    @@ -443,7 +579,8 @@ export default function RuleGroupNew() { id="description" name="description" className="form-textarea" - defaultValue={group?.description || actionData?.values?.description || ""} + value={formValues.description} + onChange={handleChange} placeholder="请输入分组描述,包括适用场景、分组目的等" >
    详细描述有助于其他用户了解该分组的用途
    @@ -456,7 +593,8 @@ export default function RuleGroupNew() { id="status" name="status" className="form-select" - defaultValue={group?.status || actionData?.values?.status || "active"} + value={formValues.status} + onChange={handleChange} > @@ -472,7 +610,7 @@ export default function RuleGroupNew() { id="sortOrder" name="sortOrder" className="form-input" - defaultValue={group?.sortOrder?.toString() || actionData?.values?.sortOrder || "0"} + defaultValue={group?.sortOrder?.toString() || "0"} placeholder="请输入排序值,数字越小排序越靠前" min="0" /> diff --git a/app/routes/rules-files.tsx b/app/routes/rules-files.tsx index e18ee3a..14a10bc 100644 --- a/app/routes/rules-files.tsx +++ b/app/routes/rules-files.tsx @@ -3,7 +3,7 @@ import { useLoaderData, useSearchParams, useNavigate } from "@remix-run/react"; import { Button } from "~/components/ui/Button"; import { Card } from "~/components/ui/Card"; import { FileIcon } from "~/components/ui/FileIcon"; -import { FilterPanel, FilterSelect, SearchFilter } from "~/components/ui/FilterPanel"; +import { FilterPanel, FilterSelect, SearchFilter, DateRangeFilter } from "~/components/ui/FilterPanel"; import { Pagination } from "~/components/ui/Pagination"; import { Table } from "~/components/ui/Table"; import { Tag } from "~/components/ui/Tag"; @@ -15,6 +15,7 @@ import { updateDocumentAuditStatus } from "~/api/evaluation_points/rules-files"; import { getDocumentTypes } from "~/api/document-types/document-types"; +import { toastService } from "~/components/ui/Toast"; export const links = () => [ { rel: "stylesheet", href: rulesFilesStyles } @@ -55,6 +56,8 @@ export async function loader({ request }: LoaderFunctionArgs) { const fileType = url.searchParams.get("fileType") || ""; const reviewStatus = url.searchParams.get("reviewStatus") || ""; const dateRange = url.searchParams.get("dateRange") || ""; + const dateFrom = url.searchParams.get("dateFrom") || ""; + const dateTo = url.searchParams.get("dateTo") || ""; const keyword = url.searchParams.get("keyword") || ""; const sortOrder = url.searchParams.get("sortOrder") || "upload_time_desc"; const currentPage = parseInt(url.searchParams.get("page") || "1", 10); @@ -70,6 +73,8 @@ export async function loader({ request }: LoaderFunctionArgs) { fileType, reviewStatus, dateRange, + dateFrom, + dateTo, keyword, sortOrder, page: currentPage, @@ -113,9 +118,11 @@ export function ErrorBoundary() { // 在文件中定义一个与路由文件名匹配的命名函数组件 export default function RulesFiles() { + const navigate = useNavigate(); const { files, documentTypes, totalCount, currentPage, pageSize } = useLoaderData(); const [searchParams, setSearchParams] = useSearchParams(); - const navigate = useNavigate(); + const dateFrom = searchParams.get('dateFrom') || ''; + const dateTo = searchParams.get('dateTo') || ''; // 处理筛选条件变更 const handleFilterChange = (e: React.ChangeEvent) => { @@ -196,14 +203,14 @@ export default function RulesFiles() { ); } - // 如果评查状态为通过,显示"所有评查点均通过" - if (file.reviewStatus === 'fail') { - return ( -
    - 统计分数为:{file.score || 0}。分数低于80分。 -
    - ); - } + // 如果评查状态为不通过,显示"统计分数为:{file.score || 0}。分数低于80分。" + // if (file.reviewStatus === 'fail') { + // return ( + //
    + // 统计分数为:{file.score || 0}。分数低于80分。 + //
    + // ); + // } // 显示问题列表 if (file.reviewStatus !== 'pass' && file.reviewStatus !== 'fail' && file.issues && file.issues.length > 0) { @@ -268,9 +275,38 @@ export default function RulesFiles() { }, 100); } catch (error) { console.error('下载文件失败:', error); - alert(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`); + toastService.error(`下载文件失败: ${error instanceof Error ? error.message : '未知错误'}`); } }; + + // 处理时间范围变更 + const handleDateChange = (field: 'dateFrom' | 'dateTo', value: string) => { + const newParams = new URLSearchParams(searchParams); + if(value) { + newParams.set(field, value); + } else { + newParams.delete(field); + } + newParams.set('page', '1'); + setSearchParams(newParams); + }; + + const handleReset = () => { + const newParams = new URLSearchParams(searchParams); + const searchInput = document.querySelector('input[name="keyword"]'); + if(searchInput) { + (searchInput as HTMLInputElement).value = ''; + } + // newParams.delete('keyword'); + + newParams.delete('dateFrom'); + newParams.delete('dateTo'); + newParams.delete('fileType'); + // newParams.delete('reviewStatus'); + newParams.delete('sortOrder'); + newParams.set('page', '1'); + setSearchParams(newParams); + }; // 文件类型选项 const fileTypeOptions = documentTypes.map((type: {id: number, name: string}) => ({ @@ -279,20 +315,20 @@ export default function RulesFiles() { })); // 评查状态选项 - const reviewStatusOptions = [ - { value: 'pass', label: '通过' }, - { value: 'warning', label: '警告' }, - { value: 'fail', label: '不通过' }, - { value: 'pending', label: '待人工确认' } - ]; + // const reviewStatusOptions = [ + // { value: 'pass', label: '通过' }, + // { value: 'warning', label: '警告' }, + // { value: 'fail', label: '不通过' }, + // { value: 'pending', label: '待人工确认' } + // ]; // 时间范围选项 - const dateRangeOptions = [ - { value: DateRange.TODAY, label: '今天' }, - { value: DateRange.WEEK, label: '本周' }, - { value: DateRange.MONTH, label: '本月' }, - // { value: DateRange.CUSTOM, label: '自定义时间段' } - ]; + // const dateRangeOptions = [ + // { value: DateRange.TODAY, label: '今天' }, + // { value: DateRange.WEEK, label: '本周' }, + // { value: DateRange.MONTH, label: '本月' }, + // // { value: DateRange.CUSTOM, label: '自定义时间段' } + // ]; // 定义表格列配置 const columns = [ @@ -423,7 +459,7 @@ export default function RulesFiles() { ]; return ( -
    +
    {/* 页面头部 */}
    @@ -440,7 +476,15 @@ export default function RulesFiles() {
    {/* 筛选区域 */} - + + + + } + > - + /> */} - */} + + handleDateChange('dateFrom', value)} + onEndDateChange={(value) => handleDateChange('dateTo', value)} + simple={true} /> + diff --git a/app/routes/rules._index.tsx b/app/routes/rules._index.tsx index c84e1e9..01579e6 100644 --- a/app/routes/rules._index.tsx +++ b/app/routes/rules._index.tsx @@ -465,7 +465,7 @@ export default function RulesIndex() { ]; return ( -
    +
    {/* 页面头部 */}

    评查点管理

    diff --git a/app/styles/pages/config-lists_index.css b/app/styles/pages/config-lists_index.css index d72694e..6cf9e81 100644 --- a/app/styles/pages/config-lists_index.css +++ b/app/styles/pages/config-lists_index.css @@ -4,7 +4,7 @@ /* 配置页面容器 */ .config-lists { - @apply p-6; + /* @apply p-6; */ } /* 表格区域 */ diff --git a/result.txt b/result.txt new file mode 100644 index 0000000000000000000000000000000000000000..dc4e9bf31ef759aee2b9c846b1ba22d511af9bbc GIT binary patch literal 1358 zcmYk6v5FNz5Jd~j1pi?$a%GjbGu=HtBpvJ68NcdBkzcOT~8-;?F*>*L=KViOn3kN2Nm+>ar~sL|p^T#u7wyM6a) zyL@?a^?Qr5|Eh{_%b(TvUyqlM$Lf_b^yf~0-^6LW>hH678*;rFxBGjwVi(W-Wf$jh zH*UpIf2KIx$KqHWo8#CDSs-Jo% zk^0H?lk1D?i|dQ)i}zE!e(5JGpW^=F{_6hf{_6hf{_6hf`E^6`sh+>uuiCHKui3BJ zuh~y`sQzZZX1`{?X1`{?*?zPAX8XRc6duH*hW=zI*F z0?oFZZGN7gE@u~m*gUx8Es6a6^utSidAMwL*H)01^bFlwCw$o5lQOJtgoOmmWnD6(7ws?c%`$U@6Cpi3Hjk>wgNhL-ce8CuQNEa!tbw44v> z&~g^YlLmWaISc%u<$hrhEzcAV(Q;;3M9Z1sQ5r;&<;+ltmNP>pTAnF%qUAmyR2qzu i