Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
S
saas-bi
项目
项目
详情
活动
周期分析
仓库
仓库
文件
提交
分支
标签
贡献者
图表
比较
统计图
议题
0
议题
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
CI / CD
CI / CD
流水线
作业
日程
统计图
Wiki
Wiki
代码片段
代码片段
成员
成员
折叠边栏
关闭边栏
活动
图像
聊天
创建新问题
作业
提交
问题看板
Open sidebar
EzijingWeb
saas-bi
Commits
10b70a6d
提交
10b70a6d
authored
3月 18, 2025
作者:
王鹏飞
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
chore: update
上级
0012a77d
隐藏空白字符变更
内嵌
并排
正在显示
44 个修改的文件
包含
1010 行增加
和
302 行删除
+1010
-302
App.scss
src/App.scss
+49
-0
App.tsx
src/App.tsx
+1
-1
base.ts
src/api/base.ts
+38
-0
AppList.tsx
src/components/AppList.tsx
+7
-2
AppProgressSteps.tsx
src/components/AppProgressSteps.tsx
+20
-0
AppSteps.tsx
src/components/AppSteps.tsx
+14
-4
AIChat.tsx
src/components/ai/AIChat.tsx
+5
-6
ChartWrap.tsx
src/components/data/ChartWrap.tsx
+47
-10
ViewDataFiledButtonModal.tsx
src/components/data/ViewDataFiledButtonModal.tsx
+1
-1
DataLayout.tsx
src/components/layout/DataLayout.tsx
+23
-23
useAI.ts
src/hooks/useAI.ts
+1
-1
useQuery.ts
src/hooks/useQuery.ts
+8
-1
Index.tsx
src/modules/data/chart/line/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/chart/pie/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/chart/radar/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/apriori/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/forest/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/fpgrowth/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/hierarchical/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/holtwinters/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/kmeans/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/linear/views/Index.tsx
+6
-0
Index.tsx
src/modules/data/digging/logistic/views/Index.tsx
+6
-0
ButtonModal.tsx
src/modules/data/digging/svm/components/ButtonModal.tsx
+158
-0
Index.tsx
src/modules/data/digging/svm/views/Index.tsx
+7
-0
Index.tsx
src/modules/data/digging/tree/views/Index.tsx
+6
-0
ButtonModal.tsx
src/modules/data/preprocess/null/components/ButtonModal.tsx
+93
-72
ButtonModal.tsx
...modules/data/preprocess/repeat/components/ButtonModal.tsx
+96
-75
ButtonModal.tsx
src/modules/data/process/mapping/components/ButtonModal.tsx
+158
-0
Index.tsx
src/modules/data/process/mapping/views/Index.tsx
+3
-2
ErrorButtonModal.tsx
...les/data/read/exploration/components/ErrorButtonModal.tsx
+7
-13
MaxButtonModal.tsx
...dules/data/read/exploration/components/MaxButtonModal.tsx
+6
-5
MinButtonModal.tsx
...dules/data/read/exploration/components/MinButtonModal.tsx
+6
-5
NullButtonModal.tsx
...ules/data/read/exploration/components/NullButtonModal.tsx
+8
-9
OtherButtonModal.tsx
...les/data/read/exploration/components/OtherButtonModal.tsx
+4
-4
RepeatButtonModal.tsx
...es/data/read/exploration/components/RepeatButtonModal.tsx
+6
-5
Index.tsx
src/modules/data/read/understanding/views/Index.tsx
+4
-4
routes.tsx
src/modules/data/routes.tsx
+45
-19
Index.tsx
src/modules/data/screen/views/Index.tsx
+6
-0
query.ts
src/modules/data/write/built/query.ts
+2
-2
Index.tsx
src/modules/data/write/built/views/Index.tsx
+2
-1
Index.tsx
src/modules/data/write/copy/views/Index.tsx
+1
-0
query.ts
src/modules/data/write/upload/query.ts
+1
-1
ai.ts
src/stores/ai.ts
+111
-36
没有找到文件。
src/App.css
→
src/App.
s
css
浏览文件 @
10b70a6d
...
@@ -92,3 +92,52 @@ body,
...
@@ -92,3 +92,52 @@ body,
padding: 0;
padding: 0;
margin: 0 20px;
margin: 0 20px;
} */
} */
.app-steps
{
.ant-steps-item-title
{
--ant-steps-title-line-height
:
100px
;
}
.app-step-box
{
width
:
90px
;
height
:
90px
;
border-radius
:
50%
;
background-color
:
#fff
;
border
:
1px
solid
#bbb
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
padding
:
14px
;
box-sizing
:
border-box
;
white-space
:
normal
;
overflow-wrap
:
break-word
;
text-align
:
center
;
line-height
:
1
.5
;
font-size
:
14px
;
}
.ant-steps-item-finish
.app-step-box
,
.ant-steps-item-process
.app-step-box
{
border
:
1px
solid
var
(
--
main-color
);
background-color
:
var
(
--
main-color
);
color
:
#fff
;
}
}
.app-process-steps
{
--ant-steps-dot-size
:
100px
!
important
;
--ant-steps-dot-current-size
:
100px
!
important
;
.app-progress-step-box
{
width
:
100%
;
height
:
100%
;
display
:
flex
;
align-items
:
center
;
justify-content
:
center
;
background-color
:
#fff
;
border
:
1px
solid
#bbb
;
border-radius
:
50%
;
}
.ant-steps-item-finish
.app-progress-step-box
{
border
:
1px
solid
var
(
--
main-color
);
background-color
:
var
(
--
main-color
);
color
:
#fff
;
}
}
src/App.tsx
浏览文件 @
10b70a6d
...
@@ -2,7 +2,7 @@ import { Suspense } from 'react'
...
@@ -2,7 +2,7 @@ import { Suspense } from 'react'
import
{
Spin
}
from
'antd'
import
{
Spin
}
from
'antd'
import
{
useRoutes
}
from
'react-router'
import
{
useRoutes
}
from
'react-router'
import
routes
from
'./router/routes'
import
routes
from
'./router/routes'
import
'./App.css'
import
'./App.
s
css'
const
App
=
()
=>
{
const
App
=
()
=>
{
const
element
=
useRoutes
(
routes
)
const
element
=
useRoutes
(
routes
)
...
...
src/api/base.ts
浏览文件 @
10b70a6d
...
@@ -1135,3 +1135,41 @@ export function getMyField() {
...
@@ -1135,3 +1135,41 @@ export function getMyField() {
})
})
return
httpRequest
.
get
(
'/api/bi/v1/data/my/field-detail'
)
return
httpRequest
.
get
(
'/api/bi/v1/data/my/field-detail'
)
}
}
// 我的数据集列表
export
function
getChartList
(
params
?:
Partial
<
{
page
:
number
;
'per-page'
:
number
}
>
)
{
return
Promise
.
resolve
({
code
:
0
,
message
:
'OK'
,
data
:
{
total
:
10
,
list
:
[
{
pk_id
:
'1'
,
type
:
'柱状图'
,
name
:
'销量统计'
,
create_user
:
'admin'
,
create_time
:
'2023-07-18 15:00:00'
,
update_time
:
'2023-07-18 15:00:00'
,
},
{
pk_id
:
'2'
,
type
:
'折线图'
,
name
:
'销售额趋势'
,
create_user
:
'admin'
,
create_time
:
'2023-07-18 15:00:00'
,
update_time
:
'2023-07-18 15:00:00'
,
},
{
pk_id
:
'3'
,
type
:
'饼图'
,
name
:
'品类分布'
,
create_user
:
'admin'
,
create_time
:
'2023-07-18 15:00:00'
,
update_time
:
'2023-07-18 15:00:00'
,
},
],
},
})
return
httpRequest
.
get
(
'/api/bi/v1/data/my/list'
,
{
params
})
}
src/components/AppList.tsx
浏览文件 @
10b70a6d
...
@@ -10,6 +10,7 @@ export interface QueryParams {
...
@@ -10,6 +10,7 @@ export interface QueryParams {
}
}
export
interface
AppListProps
extends
TableProps
{
export
interface
AppListProps
extends
TableProps
{
queryKey
?:
any
[]
fetchApi
?:
(
params
?:
QueryParams
)
=>
Promise
<
{
list
:
any
[];
total
:
number
}
>
fetchApi
?:
(
params
?:
QueryParams
)
=>
Promise
<
{
list
:
any
[];
total
:
number
}
>
filters
?:
any
[]
filters
?:
any
[]
filterAside
?:
React
.
ReactNode
filterAside
?:
React
.
ReactNode
...
@@ -21,15 +22,19 @@ export interface AppListRef {
...
@@ -21,15 +22,19 @@ export interface AppListRef {
}
}
const
AppList
=
forwardRef
<
AppListRef
,
AppListProps
>
(
const
AppList
=
forwardRef
<
AppListRef
,
AppListProps
>
(
({
fetchApi
,
filters
=
[],
filterAside
,
dataSource
=
[],
...
props
},
ref
)
=>
{
({
queryKey
=
[],
fetchApi
,
filters
=
[],
filterAside
,
dataSource
=
[],
...
props
},
ref
)
=>
{
const
[
form
]
=
Form
.
useForm
()
const
[
form
]
=
Form
.
useForm
()
const
[
queryParams
,
setQueryParams
]
=
useState
<
QueryParams
>
({
page
:
1
,
'per-page'
:
10
})
const
[
queryParams
,
setQueryParams
]
=
useState
<
QueryParams
>
({
page
:
1
,
'per-page'
:
10
})
const
{
data
,
refetch
,
isLoading
}
=
useQuery
({
const
{
data
,
refetch
,
isLoading
}
=
useQuery
({
queryKey
:
[
'appList'
,
queryParams
],
queryKey
:
[
...
queryKey
,
'appList'
,
queryParams
],
queryFn
:
async
()
=>
{
queryFn
:
async
()
=>
{
return
fetchApi
?
await
fetchApi
(
queryParams
)
:
{
list
:
dataSource
||
[],
total
:
dataSource
?.
length
||
0
}
return
fetchApi
?
await
fetchApi
(
queryParams
)
:
{
list
:
dataSource
||
[],
total
:
dataSource
?.
length
||
0
}
},
},
initialData
:
():
any
=>
{
return
{
list
:
dataSource
||
[],
total
:
dataSource
?.
length
||
0
}
},
enabled
:
!!
fetchApi
,
})
})
// 暴露方法
// 暴露方法
...
...
src/components/AppProgressSteps.tsx
0 → 100644
浏览文件 @
10b70a6d
import
type
{
StepsProps
}
from
'antd'
import
{
Spin
,
Steps
}
from
'antd'
export
default
function
AppSteps
({
...
props
}:
StepsProps
)
{
const
customDot
=
(
dot
,
{
status
})
=>
{
const
statusMap
:
any
=
{
wait
:
'待处理'
,
process
:
'处理中'
,
finish
:
'已完成'
,
}
return
(
<>
<
div
className=
"app-progress-step-box"
>
{
status
===
'process'
?
<
Spin
size=
"large"
></
Spin
>
:
statusMap
[
status
]
}
</
div
>
</>
)
}
return
<
Steps
className=
"app-process-steps"
progressDot=
{
customDot
}
labelPlacement=
"vertical"
{
...
props
}
></
Steps
>
}
src/components/AppSteps.tsx
浏览文件 @
10b70a6d
import
type
{
StepsProps
}
from
'antd'
import
type
{
StepsProps
}
from
'antd'
import
{
Popover
,
Steps
}
from
'antd'
import
{
Steps
}
from
'antd'
export
default
function
AppSteps
(
props
:
StepsProps
)
{
export
default
function
AppSteps
({
items
=
[],
...
props
}:
StepsProps
)
{
const
customDot
:
StepsProps
[
'progressDot'
]
=
(
dot
,
{
status
,
index
})
=>
<>
{
dot
}
</>
return
(
return
<
Steps
{
...
props
}
progressDot=
{
customDot
}
/>
<
Steps
className=
"app-steps"
{
...
props
}
>
{
items
.
map
((
item
,
index
)
=>
(
<
Steps
.
Step
key=
{
index
}
icon=
{
<></>
}
title=
{
<
div
className=
"app-step-box"
>
{
item
.
title
}
</
div
>
}
description=
{
item
.
description
}
/>
))
}
</
Steps
>
)
}
}
src/components/ai/AIChat.tsx
浏览文件 @
10b70a6d
import
{
useState
,
KeyboardEvent
,
useEffect
,
useRef
}
from
'react'
import
{
useState
,
KeyboardEvent
,
useEffect
,
useRef
}
from
'react'
import
{
Button
,
Card
,
FloatButton
,
Select
}
from
'antd'
import
{
Button
,
Card
,
FloatButton
,
Input
,
Select
}
from
'antd'
import
{
CircleArrowLeft
,
CircleArrowRight
}
from
'lucide-react'
import
{
CircleArrowLeft
,
CircleArrowRight
}
from
'lucide-react'
import
'./AIChat.scss'
import
{
OpenAIOutlined
,
ArrowUpOutlined
}
from
'@ant-design/icons'
import
{
OpenAIOutlined
,
ArrowUpOutlined
}
from
'@ant-design/icons'
import
TextArea
from
'antd/es/input/TextArea'
import
{
useAI
,
AIMessage
}
from
'@/hooks/useAI'
import
Markdown
from
'react-markdown'
import
Markdown
from
'react-markdown'
import
remarkGfm
from
'remark-gfm'
import
remarkGfm
from
'remark-gfm'
import
{
useAIStore
,
AIMessage
}
from
'@/stores/ai'
import
'./AIChat.scss'
export
const
MessageItem
=
({
message
}:
{
message
:
AIMessage
})
=>
{
export
const
MessageItem
=
({
message
}:
{
message
:
AIMessage
})
=>
{
return
(
return
(
...
@@ -27,7 +26,7 @@ export default function AIChat() {
...
@@ -27,7 +26,7 @@ export default function AIChat() {
setCollapsed
(
!
collapsed
)
setCollapsed
(
!
collapsed
)
}
}
const
{
ai
,
setAI
,
options
,
post
,
messages
,
isLoading
}
=
useAI
()
const
{
ai
,
setAI
,
options
,
post
,
messages
,
isLoading
}
=
useAI
Store
()
const
[
content
,
setContent
]
=
useState
(
''
)
const
[
content
,
setContent
]
=
useState
(
''
)
...
@@ -65,7 +64,7 @@ export default function AIChat() {
...
@@ -65,7 +64,7 @@ export default function AIChat() {
<
div
className=
"input-container"
>
<
div
className=
"input-container"
>
<
div
className=
"input-box"
>
<
div
className=
"input-box"
>
<
div
className=
"edit-area"
>
<
div
className=
"edit-area"
>
<
TextArea
<
Input
.
TextArea
className=
"content"
className=
"content"
autoSize
autoSize
value=
{
content
}
value=
{
content
}
...
...
src/components/data/ChartWrap.tsx
浏览文件 @
10b70a6d
import
{
Button
,
Card
,
Flex
}
from
'antd'
import
{
Button
,
Card
,
Flex
}
from
'antd'
import
{
ReactNode
}
from
'react'
import
{
ReactNode
}
from
'react'
import
AppList
,
{
AppListProps
}
from
'@/components/AppList'
import
{
getChartList
}
from
'@/api/base'
export
default
function
DataWrap
({
export
default
function
DataWrap
({
title
,
buttons
}:
{
title
:
string
;
buttons
:
ReactNode
;
children
?:
ReactNode
})
{
title
,
const
listOptions
:
AppListProps
=
{
buttons
,
fetchApi
:
async
(
params
)
=>
{
children
,
const
{
data
}
=
await
getChartList
(
params
)
}:
{
return
{
...
data
}
title
:
string
},
buttons
:
ReactNode
columns
:
[
children
?:
ReactNode
{
})
{
title
:
'序号'
,
key
:
'index'
,
render
(
_value
,
_record
,
index
)
{
return
index
+
1
},
width
:
62
,
align
:
'center'
,
},
{
title
:
'组件类型'
,
dataIndex
:
'type'
,
align
:
'center'
},
{
title
:
'组件名称'
,
dataIndex
:
'name'
,
align
:
'center'
},
{
title
:
'创建人'
,
dataIndex
:
'create_user'
,
align
:
'center'
},
{
title
:
'创建时间'
,
dataIndex
:
'create_time'
,
align
:
'center'
},
{
title
:
'更新时间'
,
dataIndex
:
'update_time'
,
align
:
'center'
},
{
title
:
'操作'
,
key
:
'x'
,
width
:
220
,
align
:
'center'
,
render
(
_value
,
record
)
{
return
(
<>
<
Button
color=
"primary"
variant=
"text"
>
查看
</
Button
>
<
Button
color=
"primary"
variant=
"text"
>
编辑
</
Button
>
<
Button
color=
"danger"
variant=
"text"
>
删除
</
Button
>
</>
)
},
},
],
}
return
(
return
(
<
Flex
gap=
{
20
}
style=
{
{
height
:
'100%'
}
}
>
<
Flex
gap=
{
20
}
style=
{
{
height
:
'100%'
}
}
>
<
Card
className=
"app-card"
title=
{
title
}
style=
{
{
flex
:
1
,
overflowX
:
'hidden'
}
}
>
<
Card
className=
"app-card"
title=
{
title
}
style=
{
{
flex
:
1
,
overflowX
:
'hidden'
}
}
>
...
@@ -19,7 +56,7 @@ export default function DataWrap({
...
@@ -19,7 +56,7 @@ export default function DataWrap({
</
Flex
>
</
Flex
>
<
Button
>
查看我的数据集
</
Button
>
<
Button
>
查看我的数据集
</
Button
>
</
Flex
>
</
Flex
>
{
children
}
<
AppList
{
...
listOptions
}
/>
</
Card
>
</
Card
>
</
Flex
>
</
Flex
>
)
)
...
...
src/components/data/ViewDataFiledButtonModal.tsx
浏览文件 @
10b70a6d
...
@@ -7,8 +7,8 @@ export default function ViewDataFiledButtonModal({ children }: { children?: stri
...
@@ -7,8 +7,8 @@ export default function ViewDataFiledButtonModal({ children }: { children?: stri
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
{
data
}
=
useDataFieldQuery
()
const
{
data
}
=
useDataFieldQuery
()
const
listOptions
:
AppListProps
=
{
const
listOptions
:
AppListProps
=
{
queryKey
:
[
'dataField'
],
columns
:
[
columns
:
[
{
{
title
:
'序号'
,
title
:
'序号'
,
...
...
src/components/layout/DataLayout.tsx
浏览文件 @
10b70a6d
...
@@ -99,16 +99,16 @@ export default function DataLayout() {
...
@@ -99,16 +99,16 @@ export default function DataLayout() {
name
:
'数据挖掘'
,
name
:
'数据挖掘'
,
path
:
'/data/digging'
,
path
:
'/data/digging'
,
children
:
[
children
:
[
{
name
:
'线性回归'
,
path
:
'/data/digging/
1
'
},
{
name
:
'线性回归'
,
path
:
'/data/digging/
linear
'
},
{
name
:
'逻辑回归'
,
path
:
'/data/digging/
2
'
},
{
name
:
'逻辑回归'
,
path
:
'/data/digging/
logistic
'
},
{
name
:
'决策树'
,
path
:
'/data/digging/
3
'
},
{
name
:
'决策树'
,
path
:
'/data/digging/
tree
'
},
{
name
:
'随机森林'
,
path
:
'/data/digging/
4
'
},
{
name
:
'随机森林'
,
path
:
'/data/digging/
forest
'
},
{
name
:
'支持向量机'
,
path
:
'/data/digging/
5
'
},
{
name
:
'支持向量机'
,
path
:
'/data/digging/
svm
'
},
{
name
:
'K-Means'
,
path
:
'/data/digging/
6
'
},
{
name
:
'K-Means'
,
path
:
'/data/digging/
kmeans
'
},
{
name
:
'层次聚类'
,
path
:
'/data/digging/
7
'
},
{
name
:
'层次聚类'
,
path
:
'/data/digging/
hierarchical
'
},
{
name
:
'Apriori'
,
path
:
'/data/digging/
8
'
},
{
name
:
'Apriori'
,
path
:
'/data/digging/
apriori
'
},
{
name
:
'FP-Growth'
,
path
:
'/data/digging/
9
'
},
{
name
:
'FP-Growth'
,
path
:
'/data/digging/
fpgrowth
'
},
{
name
:
'Holt-Winters'
,
path
:
'/data/digging/
10
'
},
{
name
:
'Holt-Winters'
,
path
:
'/data/digging/
holtwinters
'
},
],
],
},
},
{
{
...
@@ -117,19 +117,19 @@ export default function DataLayout() {
...
@@ -117,19 +117,19 @@ export default function DataLayout() {
path
:
'/data/chart'
,
path
:
'/data/chart'
,
children
:
[
children
:
[
{
name
:
'柱状图'
,
path
:
'/data/chart/bar'
},
{
name
:
'柱状图'
,
path
:
'/data/chart/bar'
},
{
name
:
'折线图'
,
path
:
'/data/chart/
2
'
},
{
name
:
'折线图'
,
path
:
'/data/chart/
line
'
},
{
name
:
'饼状图'
,
path
:
'/data/chart/
3
'
},
{
name
:
'饼状图'
,
path
:
'/data/chart/
pie
'
},
{
name
:
'雷达图'
,
path
:
'/data/chart/
4
'
},
{
name
:
'雷达图'
,
path
:
'/data/chart/
radar
'
},
{
name
:
'散点图'
,
path
:
'/data/chart/
5
'
},
{
name
:
'散点图'
,
path
:
'/data/chart/
point
'
},
{
name
:
'气泡图'
,
path
:
'/data/chart/
6
'
},
{
name
:
'气泡图'
,
path
:
'/data/chart/
bubble
'
},
{
name
:
'词云'
,
path
:
'/data/chart/
7
'
},
{
name
:
'词云'
,
path
:
'/data/chart/
wordCloud
'
},
{
name
:
'地图'
,
path
:
'/data/chart/
8
'
},
{
name
:
'地图'
,
path
:
'/data/chart/
map
'
},
{
name
:
'指标卡'
,
path
:
'/data/chart/
9
'
},
{
name
:
'指标卡'
,
path
:
'/data/chart/
indicator
'
},
{
name
:
'漏斗图'
,
path
:
'/data/chart/
10
'
},
{
name
:
'漏斗图'
,
path
:
'/data/chart/
funnel
'
},
{
name
:
'直方图'
,
path
:
'/data/chart/
11
'
},
{
name
:
'直方图'
,
path
:
'/data/chart/
histogram
'
},
{
name
:
'表格'
,
path
:
'/data/chart/
12
'
},
{
name
:
'表格'
,
path
:
'/data/chart/
table
'
},
{
name
:
'帕累托图'
,
path
:
'/data/chart/
13
'
},
{
name
:
'帕累托图'
,
path
:
'/data/chart/
pareto
'
},
{
name
:
'矩形树图'
,
path
:
'/data/chart/
14
'
},
{
name
:
'矩形树图'
,
path
:
'/data/chart/
treeMap
'
},
],
],
},
},
{
{
...
...
src/hooks/useAI.ts
浏览文件 @
10b70a6d
...
@@ -22,7 +22,7 @@ export function useAI() {
...
@@ -22,7 +22,7 @@ export function useAI() {
{
label
:
'天工'
,
value
:
'tiangong'
},
{
label
:
'天工'
,
value
:
'tiangong'
},
]
]
const
[
ai
,
setAI
]
=
useState
<
string
>
(
localStorage
.
getItem
(
'ai'
)
||
'
yiya
n'
)
const
[
ai
,
setAI
]
=
useState
<
string
>
(
localStorage
.
getItem
(
'ai'
)
||
'
qwe
n'
)
const
[
messages
,
setMessages
]
=
useState
<
AIMessage
[]
>
([])
const
[
messages
,
setMessages
]
=
useState
<
AIMessage
[]
>
([])
const
[
isLoading
,
setIsLoading
]
=
useState
<
boolean
>
(
false
)
const
[
isLoading
,
setIsLoading
]
=
useState
<
boolean
>
(
false
)
...
...
src/hooks/useQuery.ts
浏览文件 @
10b70a6d
...
@@ -51,7 +51,14 @@ export function useDataQuery(params?: Partial<{ page: number; 'per-page': number
...
@@ -51,7 +51,14 @@ export function useDataQuery(params?: Partial<{ page: number; 'per-page': number
// 查看字段详情
// 查看字段详情
export
function
useDataFieldQuery
()
{
export
function
useDataFieldQuery
()
{
const
query
=
useQuery
({
queryKey
:
[
'data-filed'
],
queryFn
:
getMyField
,
select
:
(
res
)
=>
res
.
data
})
const
query
=
useQuery
({
queryKey
:
[
'dataFiled'
],
queryFn
:
getMyField
,
select
:
(
res
)
=>
res
.
data
,
initialData
:
()
=>
{
return
{
data
:
[]
}
},
})
return
query
return
query
}
}
src/modules/data/chart/line/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
ChartWrap
from
'@/components/data/ChartWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
ChartWrap
title=
"可视化:柱状图"
buttons=
{
<
Button
type=
"primary"
>
新建柱状图
</
Button
>
}
></
ChartWrap
>
}
src/modules/data/chart/pie/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
ChartWrap
from
'@/components/data/ChartWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
ChartWrap
title=
"可视化:柱状图"
buttons=
{
<
Button
type=
"primary"
>
新建柱状图
</
Button
>
}
></
ChartWrap
>
}
src/modules/data/chart/radar/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
ChartWrap
from
'@/components/data/ChartWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
ChartWrap
title=
"可视化:柱状图"
buttons=
{
<
Button
type=
"primary"
>
新建柱状图
</
Button
>
}
></
ChartWrap
>
}
src/modules/data/digging/apriori/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:数据透视"
buttons=
{
<
Button
type=
"primary"
>
数据透视
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/forest/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据挖掘:随机森林"
buttons=
{
<
Button
type=
"primary"
>
随机森林
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/fpgrowth/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:逻辑计算"
buttons=
{
<
Button
type=
"primary"
>
逻辑计算
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/hierarchical/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:数值计算"
buttons=
{
<
Button
type=
"primary"
>
数值计算
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/holtwinters/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:数据透视"
buttons=
{
<
Button
type=
"primary"
>
数据透视
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/kmeans/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据加工:数据分组"
buttons=
{
<
Button
type=
"primary"
>
数据分组
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/linear/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据挖掘:线性回归"
buttons=
{
<
Button
type=
"primary"
>
线性回归
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/logistic/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据挖掘:逻辑回归"
buttons=
{
<
Button
type=
"primary"
>
逻辑回归
</
Button
>
}
></
DataWrap
>
}
src/modules/data/digging/svm/components/ButtonModal.tsx
0 → 100644
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Table
}
from
'antd'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
export
default
function
ButtonModal
()
{
const
{
data
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
checked
=
Form
.
useWatch
(
'checked'
,
form
)
const
[
step
,
setStep
]
=
useState
<
number
>
(
null
)
const
steps
=
[
{
title
:
'请选择值映射字段'
,
content
:
(
<>
<
Form
.
Item
label=
"值映射字段名称"
name=
"name"
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"值映射字段英文名称"
name=
"english_name"
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择值映射字段"
name=
"checked"
>
<
Radio
.
Group
>
<
Row
gutter=
{
10
}
>
{
data
.
map
((
item
)
=>
(
<
Col
span=
{
8
}
key=
{
item
.
english_name
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
</
Col
>
))
}
</
Row
>
</
Radio
.
Group
>
</
Form
.
Item
>
</>
),
},
{
title
:
'配置值映射规则'
,
content
:
(
<>
<
Form
.
Item
label=
"值映射操作字段"
>
{
checked
}
</
Form
.
Item
>
<
Form
.
Item
>
<
Table
bordered
columns=
{
[{
title
:
'序号'
},
{
title
:
'原始值'
},
{
title
:
'映射值'
}]
}
dataSource=
{
[]
}
></
Table
>
</
Form
.
Item
>
</>
),
},
{
title
:
'处理执行'
,
content
:
(
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setStep
(
2
)
}
>
开始处理
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
items=
{
[
{
title
:
(
<>
第一步
<
br
/>
新建字段
</>
),
},
{
title
:
(
<>
第二步
<
br
/>
复制数据
</>
),
},
{
title
:
(
<>
第三步
<
br
/>
值映射处理
</>
),
},
{
title
:
(
<>
第四步
<
br
/>
处理结果
</>
),
description
:
(
<>
累计处理XX个字段
<
br
/>
累计处理XX条记录
</>
),
},
]
}
/>
</
Flex
>
</>
),
},
]
return
(
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
值映射
</
Button
>
<
Modal
title=
{
steps
[
current
].
title
}
open=
{
open
}
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
1
&&
<
Button
type=
"primary"
>
AI智能建议
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
setCurrent
(
current
+
1
)
}
disabled=
{
!
checked
?.
length
}
>
下一步
</
Button
>
)
}
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
false
)
}
>
关闭
</
Button
>
)
}
</
Flex
>
}
destroyOnClose
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
Modal
>
</>
)
}
src/modules/data/digging/svm/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
{
lazy
}
from
'react'
import
DataWrap
from
'@/components/data/DataWrap'
const
ButtonModal
=
lazy
(()
=>
import
(
'../components/ButtonModal'
))
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据挖掘:支持向量机"
buttons=
{
<
ButtonModal
/>
}
></
DataWrap
>
}
src/modules/data/digging/tree/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据挖掘:决策树"
buttons=
{
<
Button
type=
"primary"
>
决策树(二分类)
</
Button
>
}
></
DataWrap
>
}
src/modules/data/preprocess/null/components/ButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Checkbox
,
Flex
,
Modal
,
Steps
,
Radio
,
Select
,
Input
,
Form
}
from
'antd'
import
{
Button
,
Checkbox
,
Flex
,
Modal
,
Radio
,
Select
,
Input
,
Form
,
Row
,
Col
,
Divider
}
from
'antd'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
{
data
}
=
useDataFieldQuery
()
const
{
data
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
checkedList
,
setCheckedList
]
=
useState
<
string
[]
>
([])
const
[
processingMethod
,
setProcessingMethod
]
=
useState
<
'unified'
|
'individual'
>
(
'unified'
)
const
[
processingRule
,
setProcessingRule
]
=
useState
<
string
>
(
'不处理'
)
const
[
specialValue
,
setSpecialValue
]
=
useState
<
string
>
(
''
)
const
plainOptions
=
data
?.
map
((
item
)
=>
{
return
{
label
:
item
.
name
,
value
:
item
.
name
,
}
})
const
onChange
=
(
list
:
string
[])
=>
{
setCheckedList
(
list
)
}
const
next
=
()
=>
{
setCurrent
(
current
+
1
)
}
const
prev
=
()
=>
{
setCurrent
(
current
-
1
)
}
const
[
form
]
=
Form
.
useForm
()
const
[
form
]
=
Form
.
useForm
()
const
checkedList
=
Form
.
useWatch
(
'checkedList'
,
form
)
||
[]
const
processingMethod
=
Form
.
useWatch
(
'processingMethod'
,
form
)
const
rule
=
Form
.
useWatch
(
'rule'
,
form
)
const
rules
=
Form
.
useWatch
(
'rules'
,
form
)
||
{}
const
methodOptions
=
[
const
methodOptions
=
[
{
label
:
'统一规则处理'
,
value
:
'unified'
},
{
label
:
'统一规则处理'
,
value
:
'unified'
},
{
label
:
'逐个配置规则处理'
,
value
:
'individual'
},
{
label
:
'逐个配置规则处理'
,
value
:
'individual'
},
]
]
const
ruleOptions
=
[
const
ruleOptions
=
[
{
label
:
'不处理'
,
value
:
'
不处理
'
},
{
label
:
'不处理'
,
value
:
'
1
'
},
{
label
:
'AI智能填充'
,
value
:
'
AI智能填充
'
},
{
label
:
'AI智能填充'
,
value
:
'
2
'
},
{
label
:
'删除'
,
value
:
'
删除
'
},
{
label
:
'删除'
,
value
:
'
3
'
},
{
label
:
'平均值填充'
,
value
:
'
平均值填充
'
},
{
label
:
'平均值填充'
,
value
:
'
4
'
},
{
label
:
'特殊值填充'
,
value
:
'
特殊值填充
'
},
{
label
:
'特殊值填充'
,
value
:
'
5
'
},
{
label
:
'热卡填充(上)'
,
value
:
'
热卡填充(上)
'
},
{
label
:
'热卡填充(上)'
,
value
:
'
6
'
},
{
label
:
'热卡填充(下)'
,
value
:
'
热卡填充(下)
'
},
{
label
:
'热卡填充(下)'
,
value
:
'
7
'
},
]
]
const
[
step
,
setStep
]
=
useState
<
number
>
(
null
)
const
steps
=
[
const
steps
=
[
{
{
title
:
'请选择缺失值字段'
,
title
:
'请选择缺失值字段'
,
content
:
<
Checkbox
.
Group
options=
{
plainOptions
}
value=
{
checkedList
}
onChange=
{
onChange
}
/>,
content
:
(
<
Form
.
Item
name=
"checkedList"
>
<
Checkbox
.
Group
>
<
Row
gutter=
{
10
}
>
{
data
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_name
}
>
<
Checkbox
value=
{
item
.
name
}
>
{
item
.
name
}
</
Checkbox
>
</
Col
>
))
}
</
Row
>
</
Checkbox
.
Group
>
</
Form
.
Item
>
),
},
},
{
{
title
:
'配置处理规则'
,
title
:
'配置处理规则'
,
content
:
(
content
:
(
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
<>
<
Form
.
Item
label=
"缺失值处理字段"
>
是否会员、会员等级
</
Form
.
Item
>
<
Form
.
Item
label=
"缺失值字段处理方法"
name=
"processingMethod"
>
<
Form
.
Item
label=
"缺失值字段处理方法"
>
<
Radio
.
Group
options=
{
methodOptions
}
/>
<
Radio
.
Group
onChange=
{
(
e
)
=>
setProcessingMethod
(
e
.
target
.
value
)
}
value=
{
processingMethod
}
options=
{
methodOptions
}
></
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
"缺失值字段处理规则"
>
<
Select
style=
{
{
width
:
200
}
}
value=
{
processingRule
}
onChange=
{
(
value
)
=>
setProcessingRule
(
value
)
}
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请填写特殊值"
>
<
Input
style=
{
{
width
:
200
}
}
value=
{
specialValue
}
onChange=
{
(
e
)
=>
setSpecialValue
(
e
.
target
.
value
)
}
placeholder=
"请输入"
/>
</
Form
.
Item
>
</
Form
.
Item
>
</
Form
>
{
/* 统一规则处理 */
}
{
processingMethod
===
'unified'
&&
(
<>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
"rule"
>
<
Select
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
{
rule
===
'5'
&&
(
<
Form
.
Item
label=
"请填写特殊值"
name=
"special"
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
)
}
</>
)
}
{
/* 逐个配置规则处理 */
}
{
processingMethod
===
'individual'
&&
checkedList
.
map
((
field
)
=>
(
<
div
key=
{
field
}
style=
{
{
marginBottom
:
10
}
}
>
<
Form
.
Item
label=
"字段"
>
{
field
}
</
Form
.
Item
>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
{
[
'rules'
,
field
,
'rule'
]
}
>
<
Select
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
{
rules
[
field
]?.
rule
===
'5'
&&
(
<
Form
.
Item
label=
"请填写特殊值"
name=
{
[
'rules'
,
field
,
'special'
]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
)
}
<
Divider
/>
</
div
>
))
}
</>
),
),
},
},
{
{
title
:
'处理执行'
,
title
:
'处理执行'
,
content
:
(
content
:
(
<>
<>
<
p
>
缺失值处理字段:
XXXXX, XXXX, XXXX, XXXX, XXXX, XXXX
</
p
>
<
p
>
缺失值处理字段:
{
checkedList
.
join
(
', '
)
}
</
p
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
>
开始处理
</
Button
>
<
Button
type=
"primary"
onClick=
{
()
=>
setStep
(
1
)
}
>
<
Steps
开始处理
labelPlacement=
"vertical"
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
items=
{
[
items=
{
[
{
{
title
:
'检查字段处理规则'
},
title
:
'检查字段处理规则'
,
{
title
:
'缺失值处理'
},
},
{
title
:
'缺失值处理'
,
},
{
{
title
:
'处理结果'
,
title
:
'处理结果'
,
description
:
(
<>
累计处理XX个字段
<
br
/>
累计处理XX条记录
</>
),
},
},
]
}
></
Steps
>
]
}
/>
</
Flex
>
</
Flex
>
</>
</>
),
),
},
},
]
]
const
title
=
steps
[
current
].
title
return
(
return
(
<>
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
处理缺失值
处理缺失值
</
Button
>
</
Button
>
<
Modal
<
Modal
title=
{
title
}
title=
{
steps
[
current
].
title
}
open=
{
open
}
open=
{
open
}
footer=
{
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
0
&&
<
Button
type=
"primary"
>
检查缺失值字段
</
Button
>
}
{
current
===
0
&&
<
Button
type=
"primary"
>
检查缺失值字段
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
prev
(
)
}
>
上一步
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
next
()
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setCurrent
(
current
+
1
)
}
disabled=
{
!
checkedList
.
length
}
>
下一步
下一步
</
Button
>
</
Button
>
)
}
)
}
...
@@ -137,7 +152,13 @@ export default function ButtonModal() {
...
@@ -137,7 +152,13 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
div
style=
{
{
marginTop
:
'20px'
}
}
>
{
steps
[
current
].
content
}
</
div
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
</>
</>
...
...
src/modules/data/preprocess/repeat/components/ButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Checkbox
,
Flex
,
Modal
,
Steps
,
Radio
,
Select
,
Input
,
Form
}
from
'antd'
import
{
Button
,
Checkbox
,
Flex
,
Modal
,
Radio
,
Select
,
Input
,
Form
,
Row
,
Col
,
Divider
}
from
'antd'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
{
data
}
=
useDataFieldQuery
()
const
{
data
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
checkedList
,
setCheckedList
]
=
useState
<
string
[]
>
([])
const
[
processingMethod
,
setProcessingMethod
]
=
useState
<
'unified'
|
'individual'
>
(
'unified'
)
const
[
processingRule
,
setProcessingRule
]
=
useState
<
string
>
(
'不处理'
)
const
[
specialValue
,
setSpecialValue
]
=
useState
<
string
>
(
''
)
const
plainOptions
=
data
?.
map
((
item
)
=>
{
return
{
label
:
item
.
name
,
value
:
item
.
name
,
}
})
const
onChange
=
(
list
:
string
[])
=>
{
setCheckedList
(
list
)
}
const
next
=
()
=>
{
setCurrent
(
current
+
1
)
}
const
prev
=
()
=>
{
setCurrent
(
current
-
1
)
}
const
[
form
]
=
Form
.
useForm
()
const
[
form
]
=
Form
.
useForm
()
const
checkedList
=
Form
.
useWatch
(
'checkedList'
,
form
)
||
[]
const
processingMethod
=
Form
.
useWatch
(
'processingMethod'
,
form
)
const
rule
=
Form
.
useWatch
(
'rule'
,
form
)
const
rules
=
Form
.
useWatch
(
'rules'
,
form
)
||
{}
const
methodOptions
=
[
const
methodOptions
=
[
{
label
:
'统一规则处理'
,
value
:
'unified'
},
{
label
:
'统一规则处理'
,
value
:
'unified'
},
{
label
:
'逐个配置规则处理'
,
value
:
'individual'
},
{
label
:
'逐个配置规则处理'
,
value
:
'individual'
},
]
]
const
ruleOptions
=
[
const
ruleOptions
=
[
{
label
:
'不处理'
,
value
:
'
不处理
'
},
{
label
:
'不处理'
,
value
:
'
1
'
},
{
label
:
'AI智能填充'
,
value
:
'
AI智能填充
'
},
{
label
:
'AI智能填充'
,
value
:
'
2
'
},
{
label
:
'删除'
,
value
:
'
删除
'
},
{
label
:
'删除'
,
value
:
'
3
'
},
{
label
:
'平均值填充'
,
value
:
'
平均值填充
'
},
{
label
:
'平均值填充'
,
value
:
'
4
'
},
{
label
:
'特殊值填充'
,
value
:
'
特殊值填充
'
},
{
label
:
'特殊值填充'
,
value
:
'
5
'
},
{
label
:
'热卡填充(上)'
,
value
:
'
热卡填充(上)
'
},
{
label
:
'热卡填充(上)'
,
value
:
'
6
'
},
{
label
:
'热卡填充(下)'
,
value
:
'
热卡填充(下)
'
},
{
label
:
'热卡填充(下)'
,
value
:
'
7
'
},
]
]
const
[
step
,
setStep
]
=
useState
<
number
>
(
null
)
const
steps
=
[
const
steps
=
[
{
{
title
:
'请选择重复值数据'
,
title
:
'请选择缺失值字段'
,
content
:
<
Checkbox
.
Group
options=
{
plainOptions
}
value=
{
checkedList
}
onChange=
{
onChange
}
/>,
content
:
(
<
Form
.
Item
name=
"checkedList"
>
<
Checkbox
.
Group
>
<
Row
gutter=
{
10
}
>
{
data
.
map
((
item
)
=>
(
<
Col
span=
{
6
}
key=
{
item
.
english_name
}
>
<
Checkbox
value=
{
item
.
name
}
>
{
item
.
name
}
</
Checkbox
>
</
Col
>
))
}
</
Row
>
</
Checkbox
.
Group
>
</
Form
.
Item
>
),
},
},
{
{
title
:
'配置处理规则'
,
title
:
'配置处理规则'
,
content
:
(
content
:
(
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
<>
<
Form
.
Item
label=
"重复值处理字段"
>
是否会员、会员等级
</
Form
.
Item
>
<
Form
.
Item
label=
"缺失值字段处理方法"
name=
"processingMethod"
>
<
Form
.
Item
label=
"重复值字段处理方法"
>
<
Radio
.
Group
options=
{
methodOptions
}
/>
<
Radio
.
Group
onChange=
{
(
e
)
=>
setProcessingMethod
(
e
.
target
.
value
)
}
value=
{
processingMethod
}
options=
{
methodOptions
}
></
Radio
.
Group
>
</
Form
.
Item
>
<
Form
.
Item
label=
"重复值字段处理规则"
>
<
Select
style=
{
{
width
:
200
}
}
value=
{
processingRule
}
onChange=
{
(
value
)
=>
setProcessingRule
(
value
)
}
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请填写特殊值"
>
<
Input
style=
{
{
width
:
200
}
}
value=
{
specialValue
}
onChange=
{
(
e
)
=>
setSpecialValue
(
e
.
target
.
value
)
}
placeholder=
"请输入"
/>
</
Form
.
Item
>
</
Form
.
Item
>
</
Form
>
{
/* 统一规则处理 */
}
{
processingMethod
===
'unified'
&&
(
<>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
"rule"
>
<
Select
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
{
rule
===
'5'
&&
(
<
Form
.
Item
label=
"请填写特殊值"
name=
"special"
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
)
}
</>
)
}
{
/* 逐个配置规则处理 */
}
{
processingMethod
===
'individual'
&&
checkedList
.
map
((
field
)
=>
(
<
div
key=
{
field
}
style=
{
{
marginBottom
:
10
}
}
>
<
Form
.
Item
label=
"字段"
>
{
field
}
</
Form
.
Item
>
<
Form
.
Item
label=
"缺失值字段处理规则"
name=
{
[
'rules'
,
field
,
'rule'
]
}
>
<
Select
options=
{
ruleOptions
}
/>
</
Form
.
Item
>
{
rules
[
field
]?.
rule
===
'5'
&&
(
<
Form
.
Item
label=
"请填写特殊值"
name=
{
[
'rules'
,
field
,
'special'
]
}
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
)
}
<
Divider
/>
</
div
>
))
}
</>
),
),
},
},
{
{
title
:
'处理执行'
,
title
:
'处理执行'
,
content
:
(
content
:
(
<>
<>
<
p
>
重复值处理字段:XXXXX, XXXX, XXXX, XXXX, XXXX, XXXX
</
p
>
<
p
>
缺失值处理字段:
{
checkedList
.
join
(
', '
)
}
</
p
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
>
开始处理
</
Button
>
<
Button
type=
"primary"
onClick=
{
()
=>
setStep
(
1
)
}
>
<
Steps
开始处理
labelPlacement=
"vertical"
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
items=
{
[
items=
{
[
{
{
title
:
'检查字段处理规则'
},
title
:
'检查字段处理规则'
,
{
title
:
'缺失值处理'
},
},
{
title
:
'重复值处理'
,
},
{
{
title
:
'处理结果'
,
title
:
'处理结果'
,
description
:
(
<>
累计处理XX个字段
<
br
/>
累计处理XX条记录
</>
),
},
},
]
}
></
Steps
>
]
}
/>
</
Flex
>
</
Flex
>
</>
</>
),
),
},
},
]
]
const
title
=
steps
[
current
].
title
return
(
return
(
<>
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
处理
重复
值
处理
缺失
值
</
Button
>
</
Button
>
<
Modal
<
Modal
title=
{
title
}
title=
{
steps
[
current
].
title
}
open=
{
open
}
open=
{
open
}
footer=
{
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
0
&&
<
Button
type=
"primary"
>
检查
重复
值字段
</
Button
>
}
{
current
===
0
&&
<
Button
type=
"primary"
>
检查
缺失
值字段
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
prev
(
)
}
>
上一步
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
next
()
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setCurrent
(
current
+
1
)
}
disabled=
{
!
checkedList
.
length
}
>
下一步
下一步
</
Button
>
</
Button
>
)
}
)
}
...
@@ -137,7 +152,13 @@ export default function ButtonModal() {
...
@@ -137,7 +152,13 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
div
style=
{
{
marginTop
:
'20px'
}
}
>
{
steps
[
current
].
content
}
</
div
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
</>
</>
...
...
src/modules/data/process/mapping/components/ButtonModal.tsx
0 → 100644
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
Button
,
Flex
,
Modal
,
Radio
,
Input
,
Form
,
Row
,
Col
,
Table
}
from
'antd'
import
{
useDataFieldQuery
}
from
'@/hooks/useQuery'
import
AppProgressSteps
from
'@/components/AppProgressSteps'
export
default
function
ButtonModal
()
{
const
{
data
}
=
useDataFieldQuery
()
const
[
open
,
setOpen
]
=
useState
(
false
)
const
[
current
,
setCurrent
]
=
useState
(
0
)
const
[
form
]
=
Form
.
useForm
()
const
checked
=
Form
.
useWatch
(
'checked'
,
form
)
const
[
step
,
setStep
]
=
useState
<
number
>
(
null
)
const
steps
=
[
{
title
:
'请选择值映射字段'
,
content
:
(
<>
<
Form
.
Item
label=
"值映射字段名称"
name=
"name"
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"值映射字段英文名称"
name=
"english_name"
>
<
Input
placeholder=
"请输入"
/>
</
Form
.
Item
>
<
Form
.
Item
label=
"请选择值映射字段"
name=
"checked"
>
<
Radio
.
Group
>
<
Row
gutter=
{
10
}
>
{
data
.
map
((
item
)
=>
(
<
Col
span=
{
8
}
key=
{
item
.
english_name
}
>
<
Radio
value=
{
item
.
name
}
>
{
item
.
name
}
</
Radio
>
</
Col
>
))
}
</
Row
>
</
Radio
.
Group
>
</
Form
.
Item
>
</>
),
},
{
title
:
'配置值映射规则'
,
content
:
(
<>
<
Form
.
Item
label=
"值映射操作字段"
>
{
checked
}
</
Form
.
Item
>
<
Form
.
Item
>
<
Table
bordered
columns=
{
[{
title
:
'序号'
},
{
title
:
'原始值'
},
{
title
:
'映射值'
}]
}
dataSource=
{
[]
}
></
Table
>
</
Form
.
Item
>
</>
),
},
{
title
:
'处理执行'
,
content
:
(
<>
<
Flex
vertical
align=
"center"
style=
{
{
marginTop
:
'20px'
}
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
setStep
(
2
)
}
>
开始处理
</
Button
>
<
AppProgressSteps
style=
{
{
margin
:
'80px'
}
}
current=
{
step
}
items=
{
[
{
title
:
(
<>
第一步
<
br
/>
新建字段
</>
),
},
{
title
:
(
<>
第二步
<
br
/>
复制数据
</>
),
},
{
title
:
(
<>
第三步
<
br
/>
值映射处理
</>
),
},
{
title
:
(
<>
第四步
<
br
/>
处理结果
</>
),
description
:
(
<>
累计处理XX个字段
<
br
/>
累计处理XX条记录
</>
),
},
]
}
/>
</
Flex
>
</>
),
},
]
return
(
<>
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
true
)
}
>
值映射
</
Button
>
<
Modal
title=
{
steps
[
current
].
title
}
open=
{
open
}
footer=
{
<
Flex
justify=
"center"
gap=
{
20
}
>
{
current
===
1
&&
<
Button
type=
"primary"
>
AI智能建议
</
Button
>
}
{
current
>
0
&&
<
Button
onClick=
{
()
=>
setCurrent
(
current
-
1
)
}
>
上一步
</
Button
>
}
{
current
<
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
setCurrent
(
current
+
1
)
}
disabled=
{
!
checked
?.
length
}
>
下一步
</
Button
>
)
}
{
current
===
steps
.
length
-
1
&&
(
<
Button
type=
"primary"
onClick=
{
()
=>
setOpen
(
false
)
}
>
关闭
</
Button
>
)
}
</
Flex
>
}
destroyOnClose
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'20px 0'
}
}
>
<
Form
form=
{
form
}
labelCol=
{
{
span
:
5
}
}
preserve=
{
false
}
>
{
steps
.
map
((
item
,
index
)
=>
(
<
div
key=
{
index
}
hidden=
{
current
!==
index
}
style=
{
{
marginTop
:
'20px'
}
}
>
{
item
.
content
}
</
div
>
))
}
</
Form
>
</
div
>
</
Modal
>
</>
)
}
src/modules/data/process/mapping/views/Index.tsx
浏览文件 @
10b70a6d
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=
{
<
Button
Modal
/
>
}
></
DataWrap
>
}
}
src/modules/data/read/exploration/components/ErrorButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Radio
,
Divider
,
Flex
,
Modal
,
Steps
}
from
'antd'
import
{
Button
,
Radio
,
Flex
,
Modal
}
from
'antd'
import
type
{
RadioChangeEvent
}
from
'antd'
import
type
{
RadioChangeEvent
}
from
'antd'
import
{
useNavigate
}
from
'react-router'
import
{
useNavigate
}
from
'react-router'
import
AppSteps
from
'@/components/AppSteps'
const
plainOptions
=
[
'会员情况'
,
'客户满意度'
,
'出生日期'
,
'访问页面时长'
,
'交易状态'
,
'商品状态'
,
'快递反馈'
]
const
plainOptions
=
[
'会员情况'
,
'客户满意度'
,
'出生日期'
,
'访问页面时长'
,
'交易状态'
,
'商品状态'
,
'快递反馈'
]
...
@@ -23,14 +24,7 @@ export default function ButtonModal() {
...
@@ -23,14 +24,7 @@ export default function ButtonModal() {
setCurrent
(
current
-
1
)
setCurrent
(
current
-
1
)
}
}
const
steps
=
[
const
steps
=
[{
title
:
'探索逻辑错误字段'
},
{
title
:
'处理逻辑错误'
}]
{
title
:
'探索逻辑错误字段'
,
},
{
title
:
'处理逻辑错误'
,
},
]
const
style
:
React
.
CSSProperties
=
{
const
style
:
React
.
CSSProperties
=
{
display
:
'flex'
,
display
:
'flex'
,
...
@@ -66,10 +60,10 @@ export default function ButtonModal() {
...
@@ -66,10 +60,10 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
Steps
current=
{
current
}
labelPlacement=
"vertical"
items=
{
steps
}
/>
<
AppSteps
current=
{
current
}
items=
{
steps
}
style=
{
{
marginBottom
:
40
}
}
/>
<
Divider
/
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
<
Flex
justify=
"space-between"
>
探索结果:
</
Flex
>
探索结果:
<
Divider
dashed
/
>
<
/
Flex
>
<
Radio
.
Group
options=
{
plainOptions
}
value=
{
value
}
onChange=
{
onChange
}
style=
{
style
}
/>
<
Radio
.
Group
options=
{
plainOptions
}
value=
{
value
}
onChange=
{
onChange
}
style=
{
style
}
/>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
...
...
src/modules/data/read/exploration/components/MaxButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Radio
,
Divider
,
Flex
,
Modal
,
Steps
}
from
'antd'
import
{
Button
,
Radio
,
Flex
,
Modal
}
from
'antd'
import
type
{
RadioChangeEvent
}
from
'antd'
import
type
{
RadioChangeEvent
}
from
'antd'
import
{
useNavigate
}
from
'react-router'
import
{
useNavigate
}
from
'react-router'
import
AppSteps
from
'@/components/AppSteps'
const
plainOptions
=
[
'会员情况'
,
'客户满意度'
,
'出生日期'
,
'访问页面时长'
,
'交易状态'
,
'商品状态'
,
'快递反馈'
]
const
plainOptions
=
[
'会员情况'
,
'客户满意度'
,
'出生日期'
,
'访问页面时长'
,
'交易状态'
,
'商品状态'
,
'快递反馈'
]
...
@@ -66,10 +67,10 @@ export default function ButtonModal() {
...
@@ -66,10 +67,10 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
Steps
current=
{
current
}
labelPlacement=
"vertical"
items=
{
steps
}
/>
<
AppSteps
current=
{
current
}
items=
{
steps
}
style=
{
{
marginBottom
:
40
}
}
/>
<
Divider
/
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
<
Flex
justify=
"space-between"
>
探索结果:
</
Flex
>
探索结果:
<
Divider
dashed
/
>
<
/
Flex
>
<
Radio
.
Group
options=
{
plainOptions
}
value=
{
value
}
onChange=
{
onChange
}
style=
{
style
}
/>
<
Radio
.
Group
options=
{
plainOptions
}
value=
{
value
}
onChange=
{
onChange
}
style=
{
style
}
/>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
...
...
src/modules/data/read/exploration/components/MinButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Radio
,
Divider
,
Flex
,
Modal
,
Steps
}
from
'antd'
import
{
Button
,
Radio
,
Flex
,
Modal
}
from
'antd'
import
type
{
RadioChangeEvent
}
from
'antd'
import
type
{
RadioChangeEvent
}
from
'antd'
import
{
useNavigate
}
from
'react-router'
import
{
useNavigate
}
from
'react-router'
import
AppSteps
from
'@/components/AppSteps'
const
plainOptions
=
[
'会员情况'
,
'客户满意度'
,
'出生日期'
,
'访问页面时长'
,
'交易状态'
,
'商品状态'
,
'快递反馈'
]
const
plainOptions
=
[
'会员情况'
,
'客户满意度'
,
'出生日期'
,
'访问页面时长'
,
'交易状态'
,
'商品状态'
,
'快递反馈'
]
...
@@ -66,10 +67,10 @@ export default function ButtonModal() {
...
@@ -66,10 +67,10 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
Steps
current=
{
current
}
labelPlacement=
"vertical"
items=
{
steps
}
/>
<
AppSteps
current=
{
current
}
items=
{
steps
}
style=
{
{
marginBottom
:
40
}
}
/>
<
Divider
/
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
<
Flex
justify=
"space-between"
>
探索结果:
</
Flex
>
探索结果:
<
Divider
dashed
/
>
<
/
Flex
>
<
Radio
.
Group
options=
{
plainOptions
}
value=
{
value
}
onChange=
{
onChange
}
style=
{
style
}
/>
<
Radio
.
Group
options=
{
plainOptions
}
value=
{
value
}
onChange=
{
onChange
}
style=
{
style
}
/>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
...
...
src/modules/data/read/exploration/components/NullButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Checkbox
,
Divider
,
Flex
,
Modal
,
Steps
}
from
'antd'
import
{
Button
,
Checkbox
,
Flex
,
Modal
}
from
'antd'
import
type
{
CheckboxProps
}
from
'antd'
import
type
{
CheckboxProps
}
from
'antd'
import
{
useNavigate
}
from
'react-router'
import
{
useNavigate
}
from
'react-router'
import
AppSteps
from
'@/components/AppSteps'
const
CheckboxGroup
=
Checkbox
.
Group
const
CheckboxGroup
=
Checkbox
.
Group
...
@@ -40,13 +41,12 @@ export default function ButtonModal() {
...
@@ -40,13 +41,12 @@ export default function ButtonModal() {
title
:
'探索缺失值字段'
,
title
:
'探索缺失值字段'
,
content
:
(
content
:
(
<>
<>
<
Flex
justify=
"space-between"
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
探索结果:
探索结果:
<
Checkbox
indeterminate=
{
indeterminate
}
onChange=
{
onCheckAllChange
}
checked=
{
checkAll
}
>
<
Checkbox
indeterminate=
{
indeterminate
}
onChange=
{
onCheckAllChange
}
checked=
{
checkAll
}
>
全选
全选
</
Checkbox
>
</
Checkbox
>
</
Flex
>
</
Flex
>
<
Divider
dashed
/>
<
CheckboxGroup
options=
{
plainOptions
}
value=
{
checkedList
}
onChange=
{
onChange
}
/>
<
CheckboxGroup
options=
{
plainOptions
}
value=
{
checkedList
}
onChange=
{
onChange
}
/>
</>
</>
),
),
...
@@ -55,8 +55,9 @@ export default function ButtonModal() {
...
@@ -55,8 +55,9 @@ export default function ButtonModal() {
title
:
'探索字段缺失值'
,
title
:
'探索字段缺失值'
,
content
:
(
content
:
(
<>
<>
<
Flex
justify=
"space-between"
>
探索结果:
</
Flex
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
<
Divider
dashed
/>
探索结果:
</
Flex
>
<
p
>
字段1:该字段有缺失值的数据有:A000001、A000002...
</
p
>
<
p
>
字段1:该字段有缺失值的数据有:A000001、A000002...
</
p
>
<
p
>
字段1:该字段有缺失值的数据有:A000001、A000002...
</
p
>
<
p
>
字段1:该字段有缺失值的数据有:A000001、A000002...
</
p
>
<
p
>
字段1:该字段有缺失值的数据有:A000001、A000002...
</
p
>
<
p
>
字段1:该字段有缺失值的数据有:A000001、A000002...
</
p
>
...
@@ -69,13 +70,12 @@ export default function ButtonModal() {
...
@@ -69,13 +70,12 @@ export default function ButtonModal() {
title
:
'填充字段缺失值'
,
title
:
'填充字段缺失值'
,
content
:
(
content
:
(
<>
<>
<
Flex
justify=
"space-between"
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
请选择需要填充的字段:
请选择需要填充的字段:
<
Checkbox
indeterminate=
{
indeterminate
}
onChange=
{
onCheckAllChange
}
checked=
{
checkAll
}
>
<
Checkbox
indeterminate=
{
indeterminate
}
onChange=
{
onCheckAllChange
}
checked=
{
checkAll
}
>
全选
全选
</
Checkbox
>
</
Checkbox
>
</
Flex
>
</
Flex
>
<
Divider
dashed
/>
<
CheckboxGroup
options=
{
plainOptions
}
value=
{
checkedList
}
onChange=
{
onChange
}
/>
<
CheckboxGroup
options=
{
plainOptions
}
value=
{
checkedList
}
onChange=
{
onChange
}
/>
</>
</>
),
),
...
@@ -116,8 +116,7 @@ export default function ButtonModal() {
...
@@ -116,8 +116,7 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
Steps
current=
{
current
}
labelPlacement=
"vertical"
items=
{
steps
}
/>
<
AppSteps
current=
{
current
}
items=
{
steps
}
style=
{
{
marginBottom
:
40
}
}
/>
<
Divider
/>
<
div
>
{
steps
[
current
].
content
}
</
div
>
<
div
>
{
steps
[
current
].
content
}
</
div
>
</
div
>
</
div
>
</
Modal
>
</
Modal
>
...
...
src/modules/data/read/exploration/components/OtherButtonModal.tsx
浏览文件 @
10b70a6d
...
@@ -32,7 +32,7 @@ export default function ButtonModal() {
...
@@ -32,7 +32,7 @@ export default function ButtonModal() {
const
dataSource
=
[
const
dataSource
=
[
{
{
key
:
'1'
,
key
:
'1'
,
name
:
'
学
段1'
,
name
:
'
字
段1'
,
max
:
99
,
max
:
99
,
min
:
'--'
,
min
:
'--'
,
mean
:
50
,
mean
:
50
,
...
@@ -46,7 +46,7 @@ export default function ButtonModal() {
...
@@ -46,7 +46,7 @@ export default function ButtonModal() {
},
},
{
{
key
:
'2'
,
key
:
'2'
,
name
:
'
学
段2'
,
name
:
'
字
段2'
,
max
:
102586
,
max
:
102586
,
min
:
'--'
,
min
:
'--'
,
mean
:
51293
,
mean
:
51293
,
...
@@ -60,7 +60,7 @@ export default function ButtonModal() {
...
@@ -60,7 +60,7 @@ export default function ButtonModal() {
},
},
{
{
key
:
'3'
,
key
:
'3'
,
name
:
'
学
段3'
,
name
:
'
字
段3'
,
max
:
859
,
max
:
859
,
min
:
'--'
,
min
:
'--'
,
mean
:
430
,
mean
:
430
,
...
@@ -74,7 +74,7 @@ export default function ButtonModal() {
...
@@ -74,7 +74,7 @@ export default function ButtonModal() {
},
},
{
{
key
:
'4'
,
key
:
'4'
,
name
:
'
学
段4'
,
name
:
'
字
段4'
,
max
:
1568
,
max
:
1568
,
min
:
'--'
,
min
:
'--'
,
mean
:
784
,
mean
:
784
,
...
...
src/modules/data/read/exploration/components/RepeatButtonModal.tsx
浏览文件 @
10b70a6d
import
{
useState
}
from
'react'
import
{
useState
}
from
'react'
import
{
Button
,
Divider
,
Flex
,
Modal
,
Steps
}
from
'antd'
import
{
Button
,
Flex
,
Modal
}
from
'antd'
import
{
useNavigate
}
from
'react-router'
import
{
useNavigate
}
from
'react-router'
import
AppSteps
from
'@/components/AppSteps'
export
default
function
ButtonModal
()
{
export
default
function
ButtonModal
()
{
const
navigate
=
useNavigate
()
const
navigate
=
useNavigate
()
...
@@ -53,10 +54,10 @@ export default function ButtonModal() {
...
@@ -53,10 +54,10 @@ export default function ButtonModal() {
width=
{
800
}
width=
{
800
}
onCancel=
{
()
=>
setOpen
(
false
)
}
>
onCancel=
{
()
=>
setOpen
(
false
)
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
div
style=
{
{
minHeight
:
300
,
padding
:
'40px 0'
}
}
>
<
Steps
current=
{
current
}
labelPlacement=
"vertical"
items=
{
steps
}
/>
<
AppSteps
current=
{
current
}
items=
{
steps
}
style=
{
{
marginBottom
:
40
}
}
/>
<
Divider
/
>
<
Flex
justify=
"space-between"
style=
{
{
marginBottom
:
20
}
}
>
<
Flex
justify=
"space-between"
>
探索结果:
</
Flex
>
探索结果:
<
Divider
dashed
/
>
<
/
Flex
>
<
p
>
1、第XX行、第XX行的数据完全一样
</
p
>
<
p
>
1、第XX行、第XX行的数据完全一样
</
p
>
<
p
>
2、第XX行、第XX行、第XX行的数据完全一样
</
p
>
<
p
>
2、第XX行、第XX行、第XX行的数据完全一样
</
p
>
</
div
>
</
div
>
...
...
src/modules/data/read/understanding/views/Index.tsx
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
import
{
Button
}
from
'antd'
import
{
useAI
}
from
'@/hooks/useAI'
import
{
useDataQuery
}
from
'@/hooks/useQuery'
import
{
useDataQuery
}
from
'@/hooks/useQuery'
import
{
useAIStore
}
from
'@/stores/ai'
export
default
function
DataWriteUpload
()
{
export
default
function
DataWriteUpload
()
{
const
{
post
}
=
useAI
()
const
{
post
,
isLoading
}
=
useAIStore
()
const
{
data
}
=
useDataQuery
()
const
{
data
}
=
useDataQuery
()
function
handleClick
(
type
:
number
)
{
function
handleClick
(
type
:
number
)
{
...
@@ -26,10 +26,10 @@ export default function DataWriteUpload() {
...
@@ -26,10 +26,10 @@ export default function DataWriteUpload() {
title=
"数据理解"
title=
"数据理解"
buttons=
{
buttons=
{
<>
<>
<
Button
type=
"primary"
onClick=
{
()
=>
handleClick
(
1
)
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
handleClick
(
1
)
}
loading=
{
isLoading
}
>
一键理解数据字段
一键理解数据字段
</
Button
>
</
Button
>
<
Button
type=
"primary"
onClick=
{
()
=>
handleClick
(
2
)
}
>
<
Button
type=
"primary"
onClick=
{
()
=>
handleClick
(
2
)
}
loading=
{
isLoading
}
>
一键梳理字段关系
一键梳理字段关系
</
Button
>
</
Button
>
</>
</>
...
...
src/modules/data/routes.tsx
浏览文件 @
10b70a6d
...
@@ -26,30 +26,56 @@ export const routes: RouteObject[] = [
...
@@ -26,30 +26,56 @@ export const routes: RouteObject[] = [
// 数据预处理
// 数据预处理
{
path
:
'preprocess'
,
element
:
<
Navigate
to=
"null"
/>
},
{
path
:
'preprocess'
,
element
:
<
Navigate
to=
"null"
/>
},
{
path
:
'preprocess/null'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/null/views/Index'
))
},
{
path
:
'preprocess/null'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/null/views/Index'
))
},
{
path
:
'preprocess/repeat'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
repeat
/views/Index'
))
},
{
path
:
'preprocess/repeat'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/max'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
max
/views/Index'
))
},
{
path
:
'preprocess/max'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/min'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
min
/views/Index'
))
},
{
path
:
'preprocess/min'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/error'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
error
/views/Index'
))
},
{
path
:
'preprocess/error'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/split'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
split
/views/Index'
))
},
{
path
:
'preprocess/split'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/space'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
space
/views/Index'
))
},
{
path
:
'preprocess/space'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/symbol'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
symbo
l/views/Index'
))
},
{
path
:
'preprocess/symbol'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
nul
l/views/Index'
))
},
{
path
:
'preprocess/type'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
type
/views/Index'
))
},
{
path
:
'preprocess/type'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/sort'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
sort
/views/Index'
))
},
{
path
:
'preprocess/sort'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
{
path
:
'preprocess/splice'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
splice
/views/Index'
))
},
{
path
:
'preprocess/splice'
,
Component
:
lazy
(()
=>
import
(
'./preprocess/
null
/views/Index'
))
},
// 数据预处理
// 数据预处理
{
path
:
'process'
,
element
:
<
Navigate
to=
"binning"
/>
},
{
path
:
'process'
,
element
:
<
Navigate
to=
"mapping"
/>
},
{
path
:
'process/binning'
,
Component
:
lazy
(()
=>
import
(
'./process/binning/views/Index'
))
},
{
path
:
'process/mapping'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/mapping'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/group'
,
Component
:
lazy
(()
=>
import
(
'./process/group/views/Index'
))
},
{
path
:
'process/binning'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/desensitization'
,
Component
:
lazy
(()
=>
import
(
'./process/desensitization/views/Index'
))
},
{
path
:
'process/group'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/date'
,
Component
:
lazy
(()
=>
import
(
'./process/date/views/Index'
))
},
{
path
:
'process/desensitization'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/string'
,
Component
:
lazy
(()
=>
import
(
'./process/string/views/Index'
))
},
{
path
:
'process/date'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/number'
,
Component
:
lazy
(()
=>
import
(
'./process/number/views/Index'
))
},
{
path
:
'process/string'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/logic'
,
Component
:
lazy
(()
=>
import
(
'./process/logic/views/Index'
))
},
{
path
:
'process/number'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/perspective'
,
Component
:
lazy
(()
=>
import
(
'./process/perspective/views/Index'
))
},
{
path
:
'process/logic'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
{
path
:
'process/perspective'
,
Component
:
lazy
(()
=>
import
(
'./process/mapping/views/Index'
))
},
// 数据挖掘
{
path
:
'digging'
,
element
:
<
Navigate
to=
"linear"
/>
},
{
path
:
'digging/linear'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/logistic'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/tree'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/forest'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/svm'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/kmeans'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/hierarchical'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/apriori'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/fpgrowth'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/views/Index'
))
},
{
path
:
'digging/holtwinters'
,
Component
:
lazy
(()
=>
import
(
'./digging/linear/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'
))
},
{
path
:
'chart/line'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/pie'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/radar'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/point'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/bubble'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/wordCloud'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/map'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/indicator'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/funnel'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/histogram'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/table'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/pareto'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'chart/treeMap'
,
Component
:
lazy
(()
=>
import
(
'./chart/bar/views/Index'
))
},
{
path
:
'screen'
,
Component
:
lazy
(()
=>
import
(
'./screen/views/Index'
))
},
],
],
},
},
],
],
...
...
src/modules/data/screen/views/Index.tsx
0 → 100644
浏览文件 @
10b70a6d
import
DataWrap
from
'@/components/data/DataWrap'
import
{
Button
}
from
'antd'
export
default
function
DataProcess
()
{
return
<
DataWrap
title=
"数据可视化大屏"
buttons=
{
<
Button
type=
"primary"
>
数据透视
</
Button
>
}
></
DataWrap
>
}
src/modules/data/write/built/query.ts
浏览文件 @
10b70a6d
...
@@ -11,7 +11,7 @@ export function useCreateDataset() {
...
@@ -11,7 +11,7 @@ export function useCreateDataset() {
mutationFn
:
(
data
:
CreateDatasetParams
)
=>
createDataset
(
data
),
mutationFn
:
(
data
:
CreateDatasetParams
)
=>
createDataset
(
data
),
onSuccess
:
()
=>
{
onSuccess
:
()
=>
{
message
.
success
(
'创建成功'
)
message
.
success
(
'创建成功'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'
appLis
t'
]
})
queryClient
.
invalidateQueries
({
queryKey
:
[
'
builtDatase
t'
]
})
},
},
})
})
}
}
...
@@ -24,7 +24,7 @@ export function useDeleteDataset() {
...
@@ -24,7 +24,7 @@ export function useDeleteDataset() {
mutationFn
:
(
data
:
{
id
:
string
})
=>
deleteDataset
(
data
),
mutationFn
:
(
data
:
{
id
:
string
})
=>
deleteDataset
(
data
),
onSuccess
:
()
=>
{
onSuccess
:
()
=>
{
message
.
success
(
'删除成功'
)
message
.
success
(
'删除成功'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'
appLis
t'
]
})
queryClient
.
invalidateQueries
({
queryKey
:
[
'
builtDatase
t'
]
})
},
},
})
})
}
}
src/modules/data/write/built/views/Index.tsx
浏览文件 @
10b70a6d
...
@@ -18,6 +18,7 @@ export default function DataWriteBuilt() {
...
@@ -18,6 +18,7 @@ export default function DataWriteBuilt() {
}
}
const
listOptions
:
AppListProps
=
{
const
listOptions
:
AppListProps
=
{
queryKey
:
[
'builtDataset'
],
fetchApi
:
async
(
params
)
=>
{
fetchApi
:
async
(
params
)
=>
{
const
{
data
}
=
await
getDatasetList
(
params
)
const
{
data
}
=
await
getDatasetList
(
params
)
return
{
...
data
}
return
{
...
data
}
...
@@ -72,7 +73,7 @@ export default function DataWriteBuilt() {
...
@@ -72,7 +73,7 @@ export default function DataWriteBuilt() {
}
}
return
(
return
(
<
Card
className=
"app-card"
title=
"内置数据集管理"
>
<
Card
className=
"app-card"
title=
"内置数据集管理"
>
<
AppList
bordered
{
...
listOptions
}
filterAside=
{
<
FormButtonModal
title=
"添加数据集"
></
FormButtonModal
>
}
></
AppList
>
<
AppList
{
...
listOptions
}
filterAside=
{
<
FormButtonModal
title=
"添加数据集"
></
FormButtonModal
>
}
></
AppList
>
</
Card
>
</
Card
>
)
)
}
}
src/modules/data/write/copy/views/Index.tsx
浏览文件 @
10b70a6d
...
@@ -12,6 +12,7 @@ export default function DataWriteCopy() {
...
@@ -12,6 +12,7 @@ export default function DataWriteCopy() {
const
industryList
=
getMapValuesByKey
(
'bi_data_industry'
)
const
industryList
=
getMapValuesByKey
(
'bi_data_industry'
)
const
listOptions
:
AppListProps
=
{
const
listOptions
:
AppListProps
=
{
queryKey
:
[
'dataWriteCopy'
],
fetchApi
:
async
(
params
)
=>
{
fetchApi
:
async
(
params
)
=>
{
const
{
data
}
=
await
getDatasetList
({
...
params
,
access_permissions
:
'1'
})
const
{
data
}
=
await
getDatasetList
({
...
params
,
access_permissions
:
'1'
})
return
{
...
data
}
return
{
...
data
}
...
...
src/modules/data/write/upload/query.ts
浏览文件 @
10b70a6d
...
@@ -11,7 +11,7 @@ export function useImportDataset() {
...
@@ -11,7 +11,7 @@ export function useImportDataset() {
onSuccess
:
()
=>
{
onSuccess
:
()
=>
{
message
.
success
(
'导入成功'
)
message
.
success
(
'导入成功'
)
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
queryClient
.
invalidateQueries
({
queryKey
:
[
'data'
]
})
queryClient
.
invalidateQueries
({
queryKey
:
[
'data
-f
iled'
]
})
queryClient
.
invalidateQueries
({
queryKey
:
[
'data
F
iled'
]
})
},
},
})
})
}
}
src/stores/ai.ts
浏览文件 @
10b70a6d
import
{
create
}
from
'zustand'
import
{
create
}
from
'zustand'
import
md5
from
'blueimp-md5'
import
axios
from
'axios'
import
axios
from
'axios'
import
{
fetchEventSource
}
from
'@fortaine/fetch-event-source'
export
interface
Message
{
export
interface
AIOption
{
label
:
string
value
:
string
}
export
interface
AIMessage
{
id
?:
string
id
?:
string
role
:
'user'
|
'assistant'
role
:
'user'
|
'assistant'
content
:
string
content
:
string
}
}
interface
State
{
interface
AI
State
{
ai
:
string
ai
:
string
setAI
:
(
ai
:
string
)
=>
void
options
:
AIOption
[]
messages
:
Message
[]
messages
:
AI
Message
[]
isLoading
:
boolean
isLoading
:
boolean
setAI
:
(
ai
:
string
)
=>
void
post
:
(
data
:
{
content
:
string
})
=>
Promise
<
void
>
post
:
(
data
:
{
content
:
string
})
=>
Promise
<
void
>
}
}
// Zustand 状态管理
export
const
useAIStore
=
create
<
AIState
>
((
set
,
get
)
=>
({
export
const
useAIStore
=
create
<
State
>
((
set
,
get
)
=>
({
ai
:
localStorage
.
getItem
(
'ai'
)
||
'qwen'
,
ai
:
localStorage
.
getItem
(
'ai'
)
||
'yiyan'
,
options
:
[
{
label
:
'文心一言'
,
value
:
'yiyan'
},
{
label
:
'DeepSeek'
,
value
:
'deepseek'
},
{
label
:
'通义千问'
,
value
:
'qwen'
},
{
label
:
'天工'
,
value
:
'tiangong'
},
],
messages
:
[],
isLoading
:
false
,
setAI
:
(
ai
)
=>
{
setAI
:
(
ai
)
=>
{
localStorage
.
setItem
(
'ai'
,
ai
)
localStorage
.
setItem
(
'ai'
,
ai
)
set
({
ai
})
set
({
ai
})
},
},
messages
:
[],
isLoading
:
false
,
post
:
async
(
data
)
=>
{
post
:
async
(
data
)
=>
{
const
{
ai
,
messages
}
=
get
()
const
{
ai
,
messages
}
=
get
()
set
({
isLoading
:
true
,
messages
:
[...
messages
,
{
role
:
'user'
,
content
:
data
.
content
}]
})
set
({
isLoading
:
true
,
messages
:
[...
messages
,
{
role
:
'user'
,
content
:
data
.
content
}]
})
try
{
try
{
let
response
=
''
switch
(
ai
)
{
switch
(
ai
)
{
case
'yiyan'
:
case
'yiyan'
:
response
=
await
yiyan
(
data
)
await
yiyan
(
data
)
break
break
case
'deepseek'
:
case
'deepseek'
:
response
=
await
deepseek
(
data
)
await
deepseek
(
data
)
break
break
case
'qwen'
:
case
'qwen'
:
response
=
await
qwen
(
data
)
await
qwen
(
data
)
break
break
case
'tiangong'
:
case
'tiangong'
:
response
=
await
tiangong
(
data
)
await
tiangong
(
data
)
break
break
default
:
default
:
throw
new
Error
(
'未找到对应的 AI 配置'
)
throw
new
Error
(
'未找到对应的 AI 配置'
)
}
}
set
((
state
)
=>
({
messages
:
[...
state
.
messages
,
{
role
:
'assistant'
,
content
:
response
}],
isLoading
:
false
,
}))
}
catch
(
err
)
{
}
catch
(
err
)
{
console
.
error
(
'AI 请求失败:'
,
err
)
console
.
error
(
'AI 请求失败:'
,
err
)
}
finally
{
set
({
isLoading
:
false
})
set
({
isLoading
:
false
})
}
}
},
},
}))
}))
// AI API 调用函数
async
function
yiyan
(
data
:
any
)
{
async
function
yiyan
(
data
:
any
)
{
const
resp
=
await
axios
.
post
(
'/api/qianfan/chat'
,
{
messages
:
[{
role
:
'user'
,
content
:
data
.
content
}]
})
const
getAccessToken
=
async
()
=>
{
return
resp
.
data
.
result
const
AK
=
'wY7bvMpkWeZbDVq9w3EDvpjU'
const
SK
=
'XJwpiJWxs5HXkOtbo6tQrvYPZFJAWdAy'
const
resp
=
await
axios
.
post
(
`/api/qianfan/oauth/2.0/token?grant_type=client_credentials&client_id=
${
AK
}
&client_secret=
${
SK
}
`
)
return
resp
.
data
.
access_token
}
const
resp
=
await
axios
.
post
(
`/api/qianfan/rpc/2.0/ai_custom/v1/wenxinworkshop/chat/eb-instant?access_token=
${
await
getAccessToken
()}
`
,
{
messages
:
[{
role
:
'user'
,
content
:
data
.
content
}],
}
)
useAIStore
.
setState
((
state
)
=>
({
messages
:
[...
state
.
messages
,
{
role
:
'assistant'
,
content
:
resp
.
data
.
result
}],
}))
}
}
async
function
deepseek
(
data
:
any
)
{
async
function
deepseek
(
data
:
any
)
{
const
resp
=
await
axios
.
post
(
'/api/deepseek/chat/completions'
,
{
const
apiKey
=
'sk-f1a6f0a7013241de8393cb2cb108e777'
model
:
'deepseek-chat'
,
const
resp
=
await
axios
.
post
(
messages
:
[{
role
:
'user'
,
content
:
data
.
content
}],
'/api/deepseek/chat/completions'
,
})
{
return
resp
.
data
.
choices
[
0
]?.
message
?.
content
||
''
model
:
'deepseek-chat'
,
messages
:
[{
role
:
'user'
,
content
:
data
.
content
}],
},
{
headers
:
{
'Content-Type'
:
'application/json'
,
Authorization
:
`Bearer
${
apiKey
}
`
},
}
)
if
(
resp
.
data
)
{
const
[
choice
=
{}]
=
resp
.
data
.
choices
useAIStore
.
setState
((
state
)
=>
({
messages
:
[...
state
.
messages
,
{
role
:
'assistant'
,
content
:
choice
.
message
.
content
}],
}))
}
}
}
async
function
qwen
(
data
:
any
)
{
async
function
qwen
(
data
:
any
)
{
const
resp
=
await
axios
.
post
(
'/api/qwen/chat/completions'
,
{
const
apiKey
=
'sk-afd0fcdb53bf4058b2068b8548820150'
model
:
'qwen-max'
,
const
resp
=
await
axios
.
post
(
messages
:
[{
role
:
'user'
,
content
:
data
.
content
}],
'/api/qwen/compatible-mode/v1/chat/completions'
,
})
{
return
resp
.
data
.
choices
[
0
]?.
message
?.
content
||
''
model
:
'qwen-max'
,
messages
:
[{
role
:
'user'
,
content
:
data
.
content
}],
},
{
headers
:
{
'Content-Type'
:
'application/json'
,
Authorization
:
`Bearer
${
apiKey
}
`
},
}
)
if
(
resp
.
data
)
{
const
[
choice
=
{}]
=
resp
.
data
.
choices
useAIStore
.
setState
((
state
)
=>
({
messages
:
[...
state
.
messages
,
{
role
:
'assistant'
,
content
:
choice
.
message
.
content
}],
}))
}
}
}
async
function
tiangong
(
data
:
any
)
{
async
function
tiangong
(
data
:
any
)
{
const
resp
=
await
axios
.
post
(
'/api/tiangong/chat'
,
{
const
appKey
=
'a8701b73637562d33a53c668a90ee3be'
chat_history
:
[{
role
:
'user'
,
content
:
data
.
content
}],
const
appSecret
=
'e191593f486bb88a39c634f46926762dddc97b9082e192af'
const
timestamp
=
Math
.
floor
(
Date
.
now
()
/
1000
).
toString
()
const
sign
=
md5
(
`
${
appKey
}${
appSecret
}${
timestamp
}
`
)
return
await
fetchEventSource
(
'/api/tiangong/sky-saas-writing/api/v1/chat'
,
{
method
:
'POST'
,
headers
:
{
'Content-Type'
:
'application/json'
,
app_key
:
appKey
,
sign
,
timestamp
,
stream
:
'true'
},
body
:
JSON
.
stringify
({
chat_history
:
[{
role
:
'user'
,
content
:
data
.
content
}],
stream_resp_type
:
'update'
,
}),
onmessage
(
res
)
{
console
.
log
(
res
.
data
)
const
message
=
JSON
.
parse
(
res
.
data
)
if
(
message
.
type
!==
1
)
return
useAIStore
.
setState
((
state
)
=>
{
const
messageId
=
message
.
conversation_id
const
messageIndex
=
state
.
messages
.
findIndex
((
msg
)
=>
msg
.
id
===
messageId
)
const
content
=
message
?.
arguments
?.[
0
]?.
messages
?.[
0
]?.
text
||
''
if
(
messageIndex
===
-
1
)
{
return
{
messages
:
[...
state
.
messages
,
{
id
:
messageId
,
role
:
'assistant'
,
content
}]
}
}
else
{
return
{
messages
:
state
.
messages
.
map
((
msg
)
=>
(
msg
.
id
===
messageId
?
{
...
msg
,
content
}
:
msg
)),
}
}
})
},
onerror
(
err
)
{
useAIStore
.
setState
({
isLoading
:
false
})
throw
err
},
})
})
return
resp
.
data
.
result
}
}
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论