diff --git a/src/api/spell-check-system.ts b/src/api/spell-check-system.ts new file mode 100644 index 00000000..37ad1c0a --- /dev/null +++ b/src/api/spell-check-system.ts @@ -0,0 +1,46 @@ +export interface SpellCheckSystemRequest { + text_input: string + enable_error_category: boolean + enable_correction_suggestion: boolean + enable_batch_processing: boolean +} + +export interface DifyRequest { + inputs: { + text_input: string + enable_error_category: boolean + enable_correction_suggestion: boolean + enable_batch_processing: boolean + } + query: string + response_mode: string +} + +export interface SpellCheckResult { + error_word: string + context: string + suggestion: string + error_type?: string +} + +export function detectSpellingErrors(params: SpellCheckSystemRequest) { + const requestBody: DifyRequest = { + inputs: { + text_input: params.text_input, + enable_error_category: params.enable_error_category, + enable_correction_suggestion: params.enable_correction_suggestion, + enable_batch_processing: params.enable_batch_processing + }, + query: '1', + response_mode: 'streaming' + } + + return fetch('https://copilot.sino-bridge.com/v1/chat-messages', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Authorization': 'Bearer app-YOaqLN0ZBsMozXCoYJqogwiA' + }, + body: JSON.stringify(requestBody) + }) +} diff --git a/src/pages/home/index.tsx b/src/pages/home/index.tsx index a1256d67..037cc39d 100644 --- a/src/pages/home/index.tsx +++ b/src/pages/home/index.tsx @@ -28,6 +28,12 @@ const cards = [ description: '智能检测和纠正中文文本中的错别字', icon: , link: '/spell-check' + }, + { + title: '错别字检测与修正系统', + description: '更智能的错别字检测与修正系统,支持分类和建议', + icon: , + link: '/spell-check-system' } ] diff --git a/src/pages/spell-check-system/index.tsx b/src/pages/spell-check-system/index.tsx new file mode 100644 index 00000000..5510f096 --- /dev/null +++ b/src/pages/spell-check-system/index.tsx @@ -0,0 +1,356 @@ +import { useState } from 'react' +import { Button, Card, Form, Input, Table, Switch, Space, message } from 'antd' +import { detectSpellingErrors, SpellCheckResult } from '@/api/spell-check-system' + +interface FeedbackItem extends SpellCheckResult { + id: string + status: 'pending' | 'confirmed' | 'rejected' +} + +const SpellCheckSystem = () => { + const [form] = Form.useForm() + const [isDetecting, setIsDetecting] = useState(false) + const [detectionResults, setDetectionResults] = useState([]) + const [feedbackData, setFeedbackData] = useState<{ + confirmed: string[] + rejected: string[] + }>({ + confirmed: [], + rejected: [] + }) + + const handleDetect = async () => { + try { + const formValues = await form.validateFields() + + // 验证用户输入文本 + if (!formValues.text_input?.trim()) { + message.warning('请输入需要检测的文本内容') + return + } + + setIsDetecting(true) + setDetectionResults([]) + + const response = await detectSpellingErrors({ + text_input: formValues.text_input, + enable_error_category: formValues.enable_error_category || false, + enable_correction_suggestion: formValues.enable_correction_suggestion !== false, + enable_batch_processing: formValues.enable_batch_processing || false + }) + + if (!response.ok) { + const errorText = await response.text() + throw new Error(`检测请求失败: ${response.status} ${errorText}`) + } + + if (!response.body) { + throw new Error('响应体为空') + } + + const reader = response.body.getReader() + const decoder = new TextDecoder('utf-8') + let buffer = '' + let fullContent = '' + let results: SpellCheckResult[] = [] + + try { + while (true) { + const { done, value } = await reader.read() + if (done) break + + buffer += decoder.decode(value, { stream: true }) + const lines = buffer.split('\n') + buffer = lines.pop() || '' + + for (const line of lines) { + const trimmedLine = line.trim() + if (!trimmedLine || trimmedLine === 'data: [DONE]') { + if (trimmedLine === 'data: [DONE]') { + message.success('检测完成') + break + } + continue + } + + if (trimmedLine.startsWith('data: ')) { + try { + const data = trimmedLine.slice(6) + const parsed = JSON.parse(data) + + if (parsed.event === 'message' && parsed.answer) { + fullContent += parsed.answer + // 尝试解析JSON结果 + try { + results = JSON.parse(fullContent) + const feedbackItems: FeedbackItem[] = results.map((item, index) => ({ + ...item, + id: `item-${index}`, + status: 'pending' as const + })) + setDetectionResults(feedbackItems) + } catch (e) { + // 解析失败,继续等待 + } + } else if (parsed.event === 'error') { + throw new Error(parsed.message || 'Dify API 返回错误') + } + } catch (parseError) { + console.warn('跳过无法解析的行:', trimmedLine) + } + } + } + } + } finally { + reader.releaseLock() + } + + if (results.length === 0 && fullContent) { + try { + results = JSON.parse(fullContent) + const feedbackItems: FeedbackItem[] = results.map((item, index) => ({ + ...item, + id: `item-${index}`, + status: 'pending' as const + })) + setDetectionResults(feedbackItems) + } catch (e) { + message.warning('检测完成,但结果格式异常') + } + } + } catch (error) { + console.error('检测错误:', error) + message.error(error instanceof Error ? error.message : '检测失败,请稍后重试') + } finally { + setIsDetecting(false) + } + } + + const handleFeedback = (id: string, status: 'confirmed' | 'rejected') => { + setDetectionResults(prev => + prev.map(item => + item.id === id ? { ...item, status } : item + ) + ) + } + + const handleSubmitFeedback = () => { + const confirmed: string[] = [] + const rejected: string[] = [] + + detectionResults.forEach(item => { + if (item.status === 'confirmed') { + confirmed.push(item.suggestion) + } else if (item.status === 'rejected') { + rejected.push(item.error_word) + } + }) + + const feedback = { confirmed, rejected } + + // 存储到本地存储 + localStorage.setItem('spell_check_feedback', JSON.stringify(feedback)) + setFeedbackData(feedback) + + message.success('反馈数据已提交并保存到本地存储') + } + + const renderFeedbackButtons = (record: FeedbackItem) => { + if (record.status !== 'pending') { + return ( + + {record.status === 'confirmed' ? '已确认' : '已否决'} + + ) + } + + return ( + + + + + ) + } + + const columns = [ + { + title: '错误词', + dataIndex: 'error_word', + key: 'error_word', + width: 120, + render: (text: string) => ( + {text} + ) + }, + { + title: '上下文', + dataIndex: 'context', + key: 'context', + ellipsis: true + }, + { + title: '建议词', + dataIndex: 'suggestion', + key: 'suggestion', + width: 120, + render: (text: string) => ( + {text} + ) + }, + { + title: '错误类型', + dataIndex: 'error_type', + key: 'error_type', + width: 120, + render: (text: string) => text || '-' + }, + { + title: '操作', + key: 'action', + width: 150, + render: (_: any, record: FeedbackItem) => renderFeedbackButtons(record) + } + ] + + return ( +
+ {/* 页面标题区 */} +
+

+ 错别字检测与修正系统 +

+
+ + + {/* 参数输入区 */} + +
+ + + + +
+ + + + + + + + + + + +
+
+
+ + {/* 操作按钮区 */} +
+ + +
+ + {/* 内容展示区 */} + 0 || isDetecting ? 'block' : 'none' + }} + > + {isDetecting ? ( +
+ 正在检测中,请稍候... +
+ ) : detectionResults.length > 0 ? ( + <> + +
+ +
+ + ) : ( +
+ 错别字检测结果将在这里显示 +
+ )} + + + + ) +} + +export default SpellCheckSystem diff --git a/src/router/index.tsx b/src/router/index.tsx index 4667030f..231190aa 100644 --- a/src/router/index.tsx +++ b/src/router/index.tsx @@ -48,6 +48,10 @@ const router: RouteObject[] = [ path: '/spell-check', element: LazyLoad(lazy(() => import('@/pages/spell-check'))) }, + { + path: '/spell-check-system', + element: LazyLoad(lazy(() => import('@/pages/spell-check-system'))) + }, { path: '/404', element: <>404 diff --git a/错别字检测系统使用说明.md b/错别字检测系统使用说明.md new file mode 100644 index 00000000..6e9370da --- /dev/null +++ b/错别字检测系统使用说明.md @@ -0,0 +1,127 @@ +# 错别字检测与修正系统 - 使用说明 + +## 系统概述 + +错别字检测与修正系统是一个基于AI技术的智能文本校对工具,能够自动识别中文文本中的错别字并提供修正建议。 + +## 功能特点 + +### 核心功能 +- **智能检测**:自动识别文本中的错别字 +- **上下文分析**:提供错误词在原文中的上下文信息 +- **修正建议**:为每个错别字提供准确的修正建议 +- **错误分类**:可选择启用错别字类型分类(如:同音字、形近字等) +- **用户反馈**:支持用户对修正建议进行确认或否决 +- **批量处理**:支持多段文本的批量检测 + +### 交互功能 +- **实时反馈**:用户可以逐条确认或否决检测结果 +- **结果统计**:自动统计确认和否决的反馈数据 +- **本地存储**:反馈数据自动保存到本地存储 + +## 页面结构 + +### 1. 页面标题区 +- 居中显示蓝色标题"错别字检测与修正系统" + +### 2. 参数输入区 +- **待检测文本**:大型文本输入框,支持多段文本 +- **配置选项**: + - 是否启用分类:控制是否显示错别字类型 + - 是否启用建议:控制是否提供修正建议(默认启用) + - 是否启用批量处理:控制是否支持多段文本处理 + +### 3. 操作按钮区 +- **检测按钮**:触发错别字检测流程 +- **重置按钮**:清空表单和结果 + +### 4. 内容展示区 +- **检测结果表格**:展示所有检测到的错别字 +- **表格列**: + - 错误词:显示识别到的错别字(红色高亮) + - 上下文:显示错别字在原文中的位置和上下文 + - 建议词:显示系统提供的修正建议(绿色高亮) + - 错误类型:显示错别字分类(如适用) + - 操作:提供确认/否决按钮供用户反馈 +- **反馈提交按钮**:提交用户反馈数据 + +## 使用方法 + +### 基本流程 + +1. **输入文本** + - 在"待检测文本"区域输入需要检测的文本内容 + - 文本支持中文,可包含多段内容 + +2. **配置选项** + - 根据需要开启/关闭各项功能开关 + - 默认启用"是否启用建议" + +3. **开始检测** + - 点击"检测"按钮 + - 系统将发送请求到Dify AI平台 + - 等待流式响应返回检测结果 + +4. **查看结果** + - 检测完成后,结果将显示在下方表格中 + - 表格显示错误词、上下文、建议词、错误类型等信息 + +5. **提交反馈** + - 对每条检测结果点击"确认"或"否决" + - 点击"提交反馈"按钮保存反馈数据 + - 数据将自动保存到本地存储 + +### API配置 + +- **请求地址**:https://copilot.sino-bridge.com/v1/chat-messages +- **鉴权方式**:Bearer Token (app-YOaqLN0ZBsMozXCoYJqogwiA) +- **请求方式**:POST +- **响应模式**:流式 (streaming) + +## 技术实现 + +### 前端技术栈 +- React 18 + TypeScript +- Ant Design 5.x(UI组件库) +- Tailwind CSS 4.x(样式框架) +- React Router DOM 6.x(路由管理) + +### 核心特性 +- **流式数据处理**:实时接收和解析Dify平台的流式响应 +- **响应式设计**:自适应不同屏幕尺寸 +- **类型安全**:完整的TypeScript类型定义 +- **模块化设计**:清晰的API和组件分离 + +## 文件结构 + +``` +src/ +├── api/ +│ └── spell-check-system.ts # API接口定义 +├── pages/ +│ └── spell-check-system/ +│ └── index.tsx # 主页面组件 +└── router/ + └── index.tsx # 路由配置 +``` + +## 访问路径 + +- 主页导航:`/` → 选择"错别字检测与修正系统"卡片 +- 直接访问:`/#/spell-check-system` + +## 注意事项 + +1. **文本长度**:建议单次检测的文本长度不超过合理范围,以保证检测效果 +2. **网络连接**:需要稳定的网络连接以访问Dify AI服务 +3. **浏览器兼容性**:推荐使用现代浏览器(Chrome、Firefox、Safari、Edge) +4. **数据存储**:用户反馈数据仅保存在本地浏览器存储中 + +## 更新日志 + +### v1.0.0 +- 初始版本发布 +- 实现基础的错别字检测功能 +- 支持流式数据处理 +- 添加用户反馈系统 +- 集成Dify AI平台