提交 eadfbd45 authored 作者: 王鹏飞's avatar 王鹏飞

chore: update

上级 25767edf
差异被折叠。
...@@ -26,8 +26,9 @@ ...@@ -26,8 +26,9 @@
"openai": "^4.87.3", "openai": "^4.87.3",
"react": "^18.3.1", "react": "^18.3.1",
"react-dom": "^18.3.1", "react-dom": "^18.3.1",
"react-markdown": "^10.1.0", "react-markdown": "^10.0.0",
"react-router": "^7.3.0", "react-router": "^7.3.0",
"react-syntax-highlighter": "^15.6.1",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz", "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.3/xlsx-0.20.3.tgz",
"zustand": "^5.0.3" "zustand": "^5.0.3"
......
...@@ -22,7 +22,12 @@ export default function AppSteps({ items, ...props }: StepsProps) { ...@@ -22,7 +22,12 @@ export default function AppSteps({ items, ...props }: StepsProps) {
) )
} }
return ( return (
<Steps className="app-process-steps" progressDot={customDot} labelPlacement="vertical" {...props}> <Steps
className="app-process-steps"
progressDot={customDot}
labelPlacement="vertical"
style={{ margin: '80px' }}
{...props}>
{items?.map(({ title, ...item }, index) => { {items?.map(({ title, ...item }, index) => {
return ( return (
<Steps.Step <Steps.Step
......
import Markdown from 'react-markdown' import Markdown from 'react-markdown'
import remarkGfm from 'remark-gfm' import remarkGfm from 'remark-gfm'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
import { dark } from 'react-syntax-highlighter/dist/esm/styles/prism'
export default function MarkdownRender(props: { children?: string }) { export default function MarkdownRender(props: { children?: string }) {
return <Markdown remarkPlugins={[remarkGfm]}>{props.children}</Markdown> return (
<Markdown
remarkPlugins={[remarkGfm]}
components={{
code(props) {
console.log(props)
const { children, className, ...rest } = props
const match = /language-(\w+)/.exec(className || '')
return match ? (
<SyntaxHighlighter
{...rest}
PreTag="div"
children={String(children).replace(/\n$/, '')}
language={match[1]}
style={dark}
/>
) : (
<code {...rest} className={className}>
{children}
</code>
)
},
}}>
{props.children}
</Markdown>
)
} }
import { useState, useEffect, useCallback } from 'react' import { useState, useEffect, useCallback, useRef } from 'react'
import aiService, { AIMessage, AIData, AI_OPTIONS, InitOptions } from '@/utils/ai' import aiService, { AIMessage, AIData, AI_OPTIONS, InitOptions } from '@/utils/ai'
export function useAI(globalOptions?: InitOptions) { export function useAI(globalOptions?: InitOptions) {
const [ai, setAI] = useState<string>(localStorage.getItem('ai') || 'qwen') const [ai, setAI] = useState<string>(localStorage.getItem('ai') || 'qwen')
const [messages, setMessages] = useState<AIMessage[]>([]) const [messages, setMessages] = useState<AIMessage[]>([])
const [message, setMessage] = useState<AIMessage | null>(null) // 存储最新的消息 const [message, setMessage] = useState<AIMessage | null>(null)
const [isLoading, setIsLoading] = useState<boolean>(false) const [isLoading, setIsLoading] = useState<boolean>(false)
// 使用 useRef 存储最新消息,避免闭包问题
const latestMessageRef = useRef<AIMessage | null>(null)
// 使用 useRef 存储消息列表,避免异步更新问题
const messagesRef = useRef<AIMessage[]>([])
useEffect(() => { useEffect(() => {
localStorage.setItem('ai', ai) localStorage.setItem('ai', ai)
}, [ai]) }, [ai])
// 更新消息的辅助函数
const updateMessage = useCallback((response: any, isNew: boolean) => {
if (isNew) {
// 新消息
const newMessage: AIMessage = {
id: response.id,
role: 'assistant',
content: response.content,
}
latestMessageRef.current = newMessage
messagesRef.current = [...messagesRef.current, newMessage]
// 更新状态
setMessage(newMessage)
setMessages(messagesRef.current)
} else {
// 更新现有消息
messagesRef.current = messagesRef.current.map((msg) => {
if (msg.id === response.id) {
const updatedMessage = {
...msg,
content: msg.content + response.content,
}
latestMessageRef.current = updatedMessage
setMessage(updatedMessage)
return updatedMessage
}
return msg
})
setMessages([...messagesRef.current])
}
}, [])
const post = useCallback( const post = useCallback(
async (data: AIData, options?: InitOptions) => { async (data: AIData, options?: InitOptions) => {
setIsLoading(true) try {
setIsLoading(true)
// 先添加用户消息(去掉 system 角色的消息)
const userMessages = data.messages.filter((item) => item.role !== 'system') // 添加用户消息
setMessages((prevMessages) => [...prevMessages, ...userMessages]) const userMessages = data.messages.filter((item) => item.role !== 'system')
messagesRef.current = [...messagesRef.current, ...userMessages]
let latestMessage: AIMessage | null = null setMessages((prev) => [...prev, ...userMessages])
const onComplete = options?.onComplete || globalOptions?.onComplete const onComplete = options?.onComplete || globalOptions?.onComplete
await aiService.post(ai, data, { await aiService.post(ai, data, {
onMessage: (response) => { onMessage: (response) => {
setMessages((prevMessages) => { const messageIndex = messagesRef.current.findIndex((msg) => msg.id === response.id)
const messageIndex = prevMessages.findIndex((msg) => msg.id === response.id) updateMessage(response, messageIndex === -1)
if (messageIndex === -1) { },
latestMessage = { id: response.id, role: 'assistant', content: response.content } onerror: (error) => {
setMessage(latestMessage) // 更新最新消息 console.error('AI service error:', error)
return [...prevMessages, latestMessage] setIsLoading(false)
} else { },
return prevMessages.map((msg) => { onclose: () => {
if (msg.id === response.id) { setIsLoading(false)
const updatedMessage = { ...msg, content: msg.content + response.content } if (latestMessageRef.current && onComplete) {
latestMessage = updatedMessage onComplete(latestMessageRef.current)
setMessage(updatedMessage) // 更新最新消息
return updatedMessage
}
return msg
})
} }
}) },
}, ...globalOptions,
onerror: () => { ...options,
setIsLoading(false) })
}, } catch (error) {
onclose: () => { console.error('Post error:', error)
setIsLoading(false) setIsLoading(false)
if (latestMessage && onComplete) onComplete(latestMessage) }
},
...globalOptions,
...options,
})
}, },
[ai] [ai, updateMessage, globalOptions]
) )
return { ai, setAI, options: AI_OPTIONS, post, messages, message, isLoading } return {
ai,
setAI,
options: AI_OPTIONS,
post,
messages,
message,
isLoading,
}
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据加工:数据透视" buttons={<Button type="primary">数据透视</Button>}></DataWrap> return <DataWrap title="数据挖掘:Apriori" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据挖掘:随机森林" buttons={<Button type="primary">随机森林</Button>}></DataWrap> return <DataWrap title="数据挖掘:随机森林" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据加工:逻辑计算" buttons={<Button type="primary">逻辑计算</Button>}></DataWrap> return <DataWrap title="数据挖掘:FP-Growth" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据加工:数值计算" buttons={<Button type="primary">数值计算</Button>}></DataWrap> return <DataWrap title="数据挖掘:层次聚类" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据加工:数据透视" buttons={<Button type="primary">数据透视</Button>}></DataWrap> return <DataWrap title="数据挖掘:Holt-Winters" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据加工:数据分组" buttons={<Button type="primary">数据分组</Button>}></DataWrap> return <DataWrap title="数据挖掘:K-Means" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据挖掘:逻辑回归" buttons={<Button type="primary">逻辑回归</Button>}></DataWrap> return <DataWrap title="数据挖掘:逻辑回归" buttons={<ButtonModal />}></DataWrap>
} }
import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
import { Button } from 'antd'
const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据挖掘:决策树" buttons={<Button type="primary">决策树(二分类)</Button>}></DataWrap> return <DataWrap title="数据挖掘:决策树" buttons={<ButtonModal />}></DataWrap>
} }
...@@ -90,7 +90,6 @@ export default function ButtonModal() { ...@@ -90,7 +90,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -90,7 +90,6 @@ export default function ButtonModal() { ...@@ -90,7 +90,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -90,7 +90,6 @@ export default function ButtonModal() { ...@@ -90,7 +90,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -152,7 +152,6 @@ export default function ButtonModal() { ...@@ -152,7 +152,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ {
......
...@@ -96,7 +96,6 @@ export default function ButtonModal() { ...@@ -96,7 +96,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -84,7 +84,6 @@ export default function ButtonModal() { ...@@ -84,7 +84,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -174,7 +174,6 @@ export default function ButtonModal() { ...@@ -174,7 +174,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -65,7 +65,6 @@ export default function ButtonModal() { ...@@ -65,7 +65,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -57,7 +57,6 @@ export default function ButtonModal() { ...@@ -57,7 +57,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -80,7 +80,6 @@ export default function ButtonModal() { ...@@ -80,7 +80,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ {
......
...@@ -178,7 +178,6 @@ export default function ButtonModal() { ...@@ -178,7 +178,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -211,7 +211,6 @@ export default function ButtonModal() { ...@@ -211,7 +211,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -198,7 +198,6 @@ export default function ButtonModal() { ...@@ -198,7 +198,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -157,7 +157,6 @@ export default function ButtonModal() { ...@@ -157,7 +157,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ {
......
...@@ -109,7 +109,6 @@ export default function ButtonModal() { ...@@ -109,7 +109,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -134,7 +134,6 @@ export default function ButtonModal() { ...@@ -134,7 +134,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -109,7 +109,6 @@ export default function ButtonModal() { ...@@ -109,7 +109,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -110,7 +110,6 @@ export default function ButtonModal() { ...@@ -110,7 +110,6 @@ export default function ButtonModal() {
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
style={{ margin: '80px' }}
current={progress} current={progress}
items={[ items={[
{ title: '新建字段' }, { title: '新建字段' },
......
...@@ -50,15 +50,15 @@ export const routes: RouteObject[] = [ ...@@ -50,15 +50,15 @@ export const routes: RouteObject[] = [
// 数据挖掘 // 数据挖掘
{ path: 'digging', element: <Navigate to="linear" /> }, { path: 'digging', element: <Navigate to="linear" /> },
{ path: 'digging/linear', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/linear', Component: lazy(() => import('./digging/linear/views/Index')) },
{ path: 'digging/logistic', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/logistic', Component: lazy(() => import('./digging/logistic/views/Index')) },
{ path: 'digging/tree', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/tree', Component: lazy(() => import('./digging/tree/views/Index')) },
{ path: 'digging/forest', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/forest', Component: lazy(() => import('./digging/forest/views/Index')) },
{ path: 'digging/svm', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/svm', Component: lazy(() => import('./digging/svm/views/Index')) },
{ path: 'digging/kmeans', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/kmeans', Component: lazy(() => import('./digging/kmeans/views/Index')) },
{ path: 'digging/hierarchical', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/hierarchical', Component: lazy(() => import('./digging/hierarchical/views/Index')) },
{ path: 'digging/apriori', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/apriori', Component: lazy(() => import('./digging/apriori/views/Index')) },
{ path: 'digging/fpgrowth', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/fpgrowth', Component: lazy(() => import('./digging/fpgrowth/views/Index')) },
{ path: 'digging/holtwinters', Component: lazy(() => import('./digging/linear/views/Index')) }, { path: 'digging/holtwinters', Component: lazy(() => import('./digging/holtwinters/views/Index')) },
// 数据可视化组件 // 数据可视化组件
{ path: 'chart', element: <Navigate to="bar" /> }, { path: 'chart', element: <Navigate to="bar" /> },
{ path: 'chart/bar', Component: lazy(() => import('./chart/bar/views/Index')) }, { path: 'chart/bar', Component: lazy(() => import('./chart/bar/views/Index')) },
......
import MarkdownRender from '@/components/MarkdownRender'
const sample = `
\`\`\`python
from sklearn.linear_model import LinearRegression\nimport numpy as np\n\n# 提取自变量和因变量\nX = np.array([['丽丽', '安全裤'], ['雅羊人', '不规则连衣裙'], ['威兰西', '网红同款连衣裙'], ['H&R', '蕾丝花边T恤'], ['H&R', '春夏新款连衣裙'], ['H&R', '秋冬款连衣裙'], ['拉夏贝尔', '泫雅风T恤'], ['艾米丽', '大码牛仔裤'], ['TARA', '春夏季新款裤子'], ['富贵人', '蕾丝花边T恤']])\ny = np.array(['丽丽', '雅羊人', '威兰西', 'H&R', 'H&R', 'H&R', '拉夏贝尔', '艾米丽', 'TARA', '富贵人'])\n\n# 将字符串数据转换为数值编码\nfrom sklearn.preprocessing import LabelEncoder\nbrand_encoder = LabelEncoder()\nproduct_encoder = LabelEncoder()\n\nX[:, 0] = brand_encoder.fit_transform(X[:, 0])\nX[:, 1] = product_encoder.fit_transform(X[:, 1])\ny = brand_encoder.transform(y)\n\n# 转换为浮点类型\nX = X.astype(float)\ny = y.astype(float)\n\n# 拟合线性回归模型\nmodel = LinearRegression(fit_intercept=True, copy_X=True, n_jobs=-1, positive=True)\ntry:\n model.fit(X, y)\n pass_status = True\nexcept Exception as e:\n pass_status = False\n\npass_status
\`\`\`
`
export default function Markdown() {
return <MarkdownRender>{sample}</MarkdownRender>
}
import { lazy } from 'react'
import type { RouteObject } from 'react-router'
export const routes: RouteObject[] = [
{
path: '/markdown',
Component: lazy(() => import('./Index')),
},
]
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论