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

chore: update

上级 6d30e308
...@@ -9,11 +9,15 @@ ...@@ -9,11 +9,15 @@
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.6.1", "@ant-design/icons": "^5.6.1",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@fortaine/fetch-event-source": "^3.0.6", "@fortaine/fetch-event-source": "^3.0.6",
"@tanstack/react-query": "^5.69.0", "@tanstack/react-query": "^5.69.0",
"@tanstack/react-query-devtools": "^5.69.0", "@tanstack/react-query-devtools": "^5.69.0",
"antd": "^5.24.4", "antd": "^5.24.4",
"axios": "^1.8.3", "axios": "^1.8.4",
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lucide-react": "^0.477.0", "lucide-react": "^0.477.0",
...@@ -160,6 +164,73 @@ ...@@ -160,6 +164,73 @@
"dev": true, "dev": true,
"license": "(Apache-2.0 AND BSD-3-Clause)" "license": "(Apache-2.0 AND BSD-3-Clause)"
}, },
"node_modules/@dnd-kit/accessibility": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.1.tgz",
"integrity": "sha512-2P+YgaXF+gRsIihwwY1gCsQSYnu9Zyj2py8kY5fFvUM1qm2WA2u639R6YNVfU4GWr+ZM5mqEsfHZZLoRONbemw==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@dnd-kit/core": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.3.1.tgz",
"integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==",
"license": "MIT",
"dependencies": {
"@dnd-kit/accessibility": "^3.1.1",
"@dnd-kit/utilities": "^3.2.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"react": ">=16.8.0",
"react-dom": ">=16.8.0"
}
},
"node_modules/@dnd-kit/modifiers": {
"version": "9.0.0",
"resolved": "https://registry.npmjs.org/@dnd-kit/modifiers/-/modifiers-9.0.0.tgz",
"integrity": "sha512-ybiLc66qRGuZoC20wdSSG6pDXFikui/dCNGthxv4Ndy8ylErY0N3KVxY2bgo7AWwIbxDmXDg3ylAFmnrjcbVvw==",
"license": "MIT",
"dependencies": {
"@dnd-kit/utilities": "^3.2.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@dnd-kit/core": "^6.3.0",
"react": ">=16.8.0"
}
},
"node_modules/@dnd-kit/sortable": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-10.0.0.tgz",
"integrity": "sha512-+xqhmIIzvAYMGfBYYnbKuNicfSsk4RksY2XdmJhT+HAC01nix6fHCztU68jooFiMUB01Ky3F0FyOvhG/BZrWkg==",
"license": "MIT",
"dependencies": {
"@dnd-kit/utilities": "^3.2.2",
"tslib": "^2.0.0"
},
"peerDependencies": {
"@dnd-kit/core": "^6.3.0",
"react": ">=16.8.0"
}
},
"node_modules/@dnd-kit/utilities": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
"integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
"license": "MIT",
"dependencies": {
"tslib": "^2.0.0"
},
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/hash": { "node_modules/@emotion/hash": {
"version": "0.8.0", "version": "0.8.0",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz",
...@@ -2007,9 +2078,9 @@ ...@@ -2007,9 +2078,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/axios": { "node_modules/axios": {
"version": "1.8.3", "version": "1.8.4",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz", "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.4.tgz",
"integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==", "integrity": "sha512-eBSYY4Y68NNlHbHBMdeDmKNtDgXWhQsJcGqzO3iLUM0GraQFSS9cVgPX5I9b3lbdFKyYoAEGAZF1DwhTaljNAw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"follow-redirects": "^1.15.6", "follow-redirects": "^1.15.6",
...@@ -6319,7 +6390,6 @@ ...@@ -6319,7 +6390,6 @@
"version": "2.8.1", "version": "2.8.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
"integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
"dev": true,
"license": "0BSD" "license": "0BSD"
}, },
"node_modules/turbo-stream": { "node_modules/turbo-stream": {
......
...@@ -11,6 +11,10 @@ ...@@ -11,6 +11,10 @@
}, },
"dependencies": { "dependencies": {
"@ant-design/icons": "^5.6.1", "@ant-design/icons": "^5.6.1",
"@dnd-kit/core": "^6.3.1",
"@dnd-kit/modifiers": "^9.0.0",
"@dnd-kit/sortable": "^10.0.0",
"@dnd-kit/utilities": "^3.2.2",
"@fortaine/fetch-event-source": "^3.0.6", "@fortaine/fetch-event-source": "^3.0.6",
"@tanstack/react-query": "^5.69.0", "@tanstack/react-query": "^5.69.0",
"@tanstack/react-query-devtools": "^5.69.0", "@tanstack/react-query-devtools": "^5.69.0",
......
...@@ -12,7 +12,7 @@ export default function ButtonModal() { ...@@ -12,7 +12,7 @@ export default function ButtonModal() {
const checked = Form.useWatch('checked', form) const checked = Form.useWatch('checked', form)
const [step, setStep] = useState<number>(null) const [step, setStep] = useState<number>(-1)
const steps = [ const steps = [
{ {
......
import { useEffect, useState } from 'react'
import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
export default function ButtonModal() {
const [searchParams] = useSearchParams()
const { isLoading, post } = useAI({
onComplete: (message) => {
try {
const parse = JSON.parse(message.content)
console.log(parse)
} catch (error) {
console.error(error)
}
},
})
const handleSearch = () => {
post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.error }],
})
}
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
useEffect(() => {
if (searchParams.get('results')) {
setOpen(true)
}
}, [searchParams])
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const initialValues = {
checked: '',
rule: '1',
}
const checked = Form.useWatch('checked', form)
const ruleOptions = [
{ label: '取该字段平均值', value: '1' },
{ label: '删除逻辑错误值', value: '2' },
{ label: '不处理', value: '3' },
]
const [step, setStep] = useState<number>(-1)
const steps = [
{
title: '请选择逻辑错误值字段',
content: (
<Form.Item name="checked" rules={[{ required: true, message: '请选择逻辑错误值字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={6} 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 label="处理规则" name="rule" rules={[{ required: true, message: '请选择处理规则' }]}>
<Radio.Group options={ruleOptions} />
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<p>逻辑错误值处理字段:{checked}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
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 === 0 && (
<Button type="primary" loading={isLoading} onClick={handleSearch}>
检查逻辑错误值字段
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked}>
下一步
</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} initialValues={initialValues}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
</div>
</Modal>
</>
)
}
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 ( return <DataWrap title="数据预处理:逻辑错误处理" buttons={<ButtonModal />}></DataWrap>
<DataWrap
title="数据预处理:逻辑错误值处理"
buttons={
<>
<Button type="primary">处理逻辑错误值</Button>
</>
}></DataWrap>
)
} }
import { useEffect, useState } from 'react'
import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
export default function ButtonModal() {
const [searchParams] = useSearchParams()
const { isLoading, post } = useAI({
onComplete: (message) => {
try {
const parse = JSON.parse(message.content)
console.log(parse)
} catch (error) {
console.error(error)
}
},
})
const handleSearch = () => {
post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.max }],
})
}
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
useEffect(() => {
if (searchParams.get('results')) {
setOpen(true)
}
}, [searchParams])
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const initialValues = {
checked: '',
rule: '1',
}
const checked = Form.useWatch('checked', form)
const ruleOptions = [
{ label: '取该字段平均值', value: '1' },
{ label: '删除过大值', value: '2' },
{ label: '不处理', value: '3' },
]
const [step, setStep] = useState<number>(-1)
const steps = [
{
title: '请选择过大值字段',
content: (
<Form.Item name="checked" rules={[{ required: true, message: '请选择过大值字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={6} 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 label="处理规则" name="rule" rules={[{ required: true, message: '请选择处理规则' }]}>
<Radio.Group options={ruleOptions} />
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<p>过大值处理字段:{checked}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
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 === 0 && (
<Button type="primary" loading={isLoading} onClick={handleSearch}>
检查过大值字段
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked}>
下一步
</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} initialValues={initialValues}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
</div>
</Modal>
</>
)
}
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 ( return <DataWrap title="数据预处理:过大值处理" buttons={<ButtonModal />}></DataWrap>
<DataWrap
title="数据预处理:过大值处理"
buttons={
<>
<Button type="primary">处理过大值</Button>
</>
}></DataWrap>
)
} }
import { useEffect, useState } from 'react'
import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
export default function ButtonModal() {
const [searchParams] = useSearchParams()
const { isLoading, post } = useAI({
onComplete: (message) => {
try {
const parse = JSON.parse(message.content)
console.log(parse)
} catch (error) {
console.error(error)
}
},
})
const handleSearch = () => {
post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.max }],
})
}
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
useEffect(() => {
if (searchParams.get('results')) {
setOpen(true)
}
}, [searchParams])
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const initialValues = {
checked: '',
rule: '1',
}
const checked = Form.useWatch('checked', form)
const ruleOptions = [
{ label: '取该字段平均值', value: '1' },
{ label: '删除过小值', value: '2' },
{ label: '不处理', value: '3' },
]
const [step, setStep] = useState<number>(-1)
const steps = [
{
title: '请选择过小值字段',
content: (
<Form.Item name="checked" rules={[{ required: true, message: '请选择过小值字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={6} 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 label="处理规则" name="rule" rules={[{ required: true, message: '请选择处理规则' }]}>
<Radio.Group options={ruleOptions} />
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<p>过小值处理字段:{checked}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
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 === 0 && (
<Button type="primary" loading={isLoading} onClick={handleSearch}>
检查过小值字段
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked}>
下一步
</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} initialValues={initialValues}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
</div>
</Modal>
</>
)
}
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 ( return <DataWrap title="数据预处理:过小值处理" buttons={<ButtonModal />}></DataWrap>
<DataWrap
title="数据预处理:过小值处理"
buttons={
<>
<Button type="primary">处理过小值</Button>
</>
}></DataWrap>
)
} }
...@@ -2,6 +2,7 @@ import { lazy } from 'react' ...@@ -2,6 +2,7 @@ import { lazy } from 'react'
import DataWrap from '@/components/data/DataWrap' import DataWrap from '@/components/data/DataWrap'
const ButtonModal = lazy(() => import('../components/ButtonModal')) const ButtonModal = lazy(() => import('../components/ButtonModal'))
export default function DataProcess() { export default function DataProcess() {
return <DataWrap title="数据预处理:缺失值处理" buttons={<ButtonModal />}></DataWrap> return <DataWrap title="数据预处理:缺失值处理" buttons={<ButtonModal />}></DataWrap>
} }
import { useState } from 'react' import { useEffect, useState } from 'react'
import { Button, Checkbox, Flex, Modal, Radio, Select, Input, Form, Row, Col, Divider } from 'antd' import { Button, Checkbox, Flex, Modal, Radio, Form, Row, Col, Empty } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps' import AppProgressSteps from '@/components/AppProgressSteps'
import { useSearchParams } from 'react-router'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
export default function ButtonModal() { export default function ButtonModal() {
const { data } = useDataFieldQuery() const [searchParams] = useSearchParams()
const [results, setResults] = useState<Array<{ lines: number[]; desc: string }>>([
{ lines: [1, 3], desc: '第1行、第3行的数据完全一样' },
{ lines: [2, 8], desc: '第2行、第8行的数据完全一样' },
])
useEffect(() => {
if (searchParams.get('results')) {
setResults(JSON.parse(searchParams.get('results') || '') as any)
setOpen(true)
}
}, [searchParams])
const { isLoading, post } = useAI({
onComplete: (message) => {
try {
const parse = JSON.parse(message.content)
console.log(parse)
if (parse.results.length) form.setFieldValue('checkedList', parse.results.map((item: any) => item.name) || [])
} catch (error) {
console.error(error)
}
},
})
const handleSearch = () => {
post({ response_format: { type: 'json_object' }, messages: [{ role: 'user', content: prompt.repeat }] })
}
const [open, setOpen] = useState(false) const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0) const [current, setCurrent] = useState(0)
const [form] = Form.useForm() const [form] = Form.useForm()
const initialValues = {
rule: '1',
}
const checkedList = Form.useWatch('checkedList', form) || [] const checkedList: string[] = Form.useWatch('checkedList', form) || []
const processingMethod = Form.useWatch('processingMethod', form)
const rule = Form.useWatch('rule', form)
const rules = Form.useWatch('rules', form) || {}
const methodOptions = [
{ label: '统一规则处理', value: 'unified' },
{ label: '逐个配置规则处理', value: 'individual' },
]
const ruleOptions = [ const ruleOptions = [
{ label: '不处理', value: '1' }, { label: '保留1条,删除剩余重复数据', value: '1' },
{ label: 'AI智能填充', value: '2' }, { label: '全部删除', value: '2' },
{ label: '删除', value: '3' }, { label: '不处理', value: '3' },
{ label: '平均值填充', value: '4' },
{ label: '特殊值填充', value: '5' },
{ label: '热卡填充(上)', value: '6' },
{ label: '热卡填充(下)', value: '7' },
] ]
const [step, setStep] = useState<number>(null) const [step, setStep] = useState<number>(-1)
const steps = [ const steps = [
{ {
title: '请选择缺失值字段', title: '请选择重复值数据',
content: ( content: (
<Form.Item name="checkedList"> <Form.Item name="checkedList">
<Checkbox.Group> <Checkbox.Group>
<Row gutter={[10, 10]}> <Row gutter={[10, 10]}>
{data.map((item) => ( {results.map((item, index) => (
<Col span={6} key={item.english_name}> <Col span={24} key={index}>
<Checkbox value={item.name}>{item.name}</Checkbox> <Checkbox value={item.desc}>{item.desc}</Checkbox>
</Col> </Col>
))} ))}
</Row> </Row>
</Checkbox.Group> </Checkbox.Group>
{!results.length && <Empty></Empty>}
</Form.Item> </Form.Item>
), ),
}, },
...@@ -53,41 +74,16 @@ export default function ButtonModal() { ...@@ -53,41 +74,16 @@ export default function ButtonModal() {
title: '配置处理规则', title: '配置处理规则',
content: ( content: (
<> <>
<Form.Item label="缺失值字段处理方法" name="processingMethod"> <Form.Item label="要处理的重复值数据">
<Radio.Group options={methodOptions} /> {checkedList.map((item, index) => (
</Form.Item> <p key={index}>
{index + 1}{item}
{/* 统一规则处理 */} </p>
{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>
))} ))}
</Form.Item>
<Form.Item label="处理规则" name="rule">
<Radio.Group options={ruleOptions} />
</Form.Item>
</> </>
), ),
}, },
...@@ -95,7 +91,6 @@ export default function ButtonModal() { ...@@ -95,7 +91,6 @@ export default function ButtonModal() {
title: '处理执行', title: '处理执行',
content: ( content: (
<> <>
<p>缺失值处理字段:{checkedList.join(', ')}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}> <Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}> <Button type="primary" onClick={() => setStep(1)}>
开始处理 开始处理
...@@ -104,10 +99,32 @@ export default function ButtonModal() { ...@@ -104,10 +99,32 @@ export default function ButtonModal() {
style={{ margin: '80px' }} style={{ margin: '80px' }}
current={step} current={step}
items={[ items={[
{ title: '检查字段处理规则' },
{ title: '缺失值处理' },
{ {
title: '处理结果', title: (
<>
第一步
<br />
检查字段处理规则
</>
),
},
{
title: (
<>
第二步
<br />
重复值处理
</>
),
},
{
title: (
<>
第三步
<br />
处理结果
</>
),
description: ( description: (
<> <>
累计处理XX个字段 累计处理XX个字段
...@@ -127,14 +144,18 @@ export default function ButtonModal() { ...@@ -127,14 +144,18 @@ export default function ButtonModal() {
return ( return (
<> <>
<Button type="primary" onClick={() => setOpen(true)}> <Button type="primary" onClick={() => setOpen(true)}>
处理缺失 处理重复
</Button> </Button>
<Modal <Modal
title={steps[current].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" loading={isLoading} onClick={handleSearch}>
检查重复值字段
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>} {current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && ( {current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checkedList.length}> <Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checkedList.length}>
...@@ -152,7 +173,7 @@ export default function ButtonModal() { ...@@ -152,7 +173,7 @@ 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' }}>
<Form form={form} labelCol={{ span: 5 }} preserve={false}> <Form form={form} labelCol={{ span: 5 }} preserve={false} initialValues={initialValues}>
{steps.map((item, index) => ( {steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}> <div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content} {item.content}
......
import React, { useEffect, useMemo, useState, useContext } from 'react'
import { HolderOutlined } from '@ant-design/icons'
import { DndContext, useSensor, useSensors, PointerSensor, KeyboardSensor, DragEndEvent } from '@dnd-kit/core'
import { restrictToVerticalAxis } from '@dnd-kit/modifiers'
import { SortableContext, useSortable, verticalListSortingStrategy, arrayMove } from '@dnd-kit/sortable'
import { CSS } from '@dnd-kit/utilities'
import { Button, Flex, Modal, Form, Table, Radio } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import type { TableColumnsType } from 'antd'
interface DataType {
key: number
name: string
raw_value: string
new_value: string
}
interface RowContextProps {
setActivatorNodeRef?: (element: HTMLElement | null) => void
listeners?: any
}
const RowContext = React.createContext<RowContextProps>({})
const DragHandle: React.FC = () => {
const { setActivatorNodeRef, listeners } = useContext(RowContext)
return (
<Button
type="text"
size="small"
icon={<HolderOutlined />}
style={{ cursor: 'grab' }}
ref={setActivatorNodeRef}
{...listeners}
/>
)
}
export default function ButtonModal() {
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const [dataSource, setDataSource] = useState<DataType[]>([])
const [step, setStep] = useState<number>(-1)
useEffect(() => {
if (fields?.length) {
setDataSource(
fields.map((item: any, index) => ({
key: index + 1,
...item,
new_value: '',
}))
)
}
}, [fields])
const handleValueChange = (value: string, key: number) => {
setDataSource((prevDataSource) =>
prevDataSource.map((item) => (item.key === key ? { ...item, new_value: value } : item))
)
}
const onDragEnd = ({ active, over }: DragEndEvent) => {
if (active.id !== over?.id) {
setDataSource((prevState) => {
const activeIndex = prevState.findIndex((record) => record.key === active.id)
const overIndex = prevState.findIndex((record) => record.key === over?.id)
return arrayMove(prevState, activeIndex, overIndex)
})
}
}
const sensors = useSensors(
useSensor(PointerSensor, {
activationConstraint: { distance: 5 },
}),
useSensor(KeyboardSensor)
)
const options = [
{ label: '无序', value: '1' },
{ label: '升序', value: '2' },
{ label: '降序', value: '3' },
]
const columns: TableColumnsType<DataType> = [
{ key: 'sort', align: 'center', width: 80, render: () => <DragHandle /> },
{ title: '字段名称', dataIndex: 'name', align: 'center' },
{
title: '排序方式',
dataIndex: 'new_value',
align: 'center',
render: (_, record) => (
<Radio.Group
options={options}
value={record.new_value}
onChange={(e) => handleValueChange(e.target.value, record.key)}
/>
),
},
]
const steps = [
{
title: '请选择转换字段',
content: (
<Form.Item>
<DndContext modifiers={[restrictToVerticalAxis]} sensors={sensors} onDragEnd={onDragEnd}>
<SortableContext items={dataSource.map((i) => i.key)} strategy={verticalListSortingStrategy}>
<Table<DataType>
bordered
pagination={false}
rowKey="key"
components={{ body: { row: DraggableRow } }}
columns={columns}
dataSource={dataSource}
/>
</SortableContext>
</DndContext>
</Form.Item>
),
},
{
title: '处理执行',
content: (
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[{ title: '第一步\n开始' }, { title: '第二步\n数据排序' }, { title: '第三步\n处理结果' }]}
/>
</Flex>
),
},
]
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
数据排序
</Button>
<Modal
title={steps[current].title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)}>
下一步
</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>
</>
)
}
interface RowProps extends React.HTMLAttributes<HTMLTableRowElement> {
'data-row-key': number
}
const DraggableRow: React.FC<RowProps> = (props) => {
const { attributes, listeners, setNodeRef, setActivatorNodeRef, transform, transition, isDragging } = useSortable({
id: props['data-row-key'],
})
const style: React.CSSProperties = {
...props.style,
transform: CSS.Translate.toString(transform),
transition,
...(isDragging ? { position: 'relative', zIndex: 9999 } : {}),
}
const contextValue = useMemo<RowContextProps>(
() => ({ setActivatorNodeRef, listeners }),
[setActivatorNodeRef, listeners]
)
return (
<RowContext.Provider value={contextValue}>
<tr {...props} ref={setNodeRef} style={style} {...attributes} />
</RowContext.Provider>
)
}
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 { useState } from 'react'
import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt'
export default function ButtonModal() {
const { isLoading, post } = useAI({
onComplete: (message) => {
try {
const parse = JSON.parse(message.content)
console.log(parse)
} catch (error) {
console.error(error)
}
},
})
const handleSearch = () => {
post({
response_format: { type: 'json_object' },
messages: [{ role: 'user', content: prompt.max }],
})
}
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const initialValues = {
checked: '',
rule: '1',
}
const checked = Form.useWatch('checked', form)
const ruleOptions = [
{ label: '开头去空格', value: '1' },
{ label: '结尾去空格', value: '2' },
{ label: '中间去空格', value: '3' },
{ label: '全部去空格', value: '4' },
]
const [step, setStep] = useState<number>(-1)
const steps = [
{
title: '请选择数据去空格字段',
content: (
<Form.Item name="checked" rules={[{ required: true, message: '请选择数据去空格字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={6} 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 label="处理规则" name="rule" rules={[{ required: true, message: '请选择处理规则' }]}>
<Radio.Group options={ruleOptions} />
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<p>数据去空格处理字段:{checked}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
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 === 0 && (
<Button type="primary" loading={isLoading} onClick={handleSearch}>
AI去空格字段分析与建议
</Button>
)}
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked}>
下一步
</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} initialValues={initialValues}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
</div>
</Modal>
</>
)
}
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 ( return <DataWrap title="数据预处理:数据去空格" buttons={<ButtonModal />}></DataWrap>
<DataWrap
title="数据预处理:数据去空格"
buttons={
<>
<Button type="primary">数据去空格</Button>
</>
}></DataWrap>
)
} }
import { useState } from 'react'
import { Button, Flex, Modal, Radio, Input, Form, Select, message } from 'antd'
import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
export default function ButtonModal() {
const { data = { list: [] } } = useDataQuery() // Default value to prevent data being undefined
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const [step, setStep] = useState(-1)
const [concatenatedFields, setConcatenatedFields] = useState<{ field: string; order: number }[]>([])
// Process the concatenation
const handleStart = () => {
setStep(0)
// Simulate processing steps with timeouts
setTimeout(() => {
setStep(1)
setTimeout(() => {
setStep(3)
message.success('数据拼接处理完成!')
}, 1000)
}, 1000)
}
// Add concatenation field
const addConcatenationField = () => {
const newField = form.getFieldValue('fieldToAdd')
if (!newField) {
message.warning('请选择要添加的字段')
return
}
const updatedFields = [
...concatenatedFields,
{
field: newField,
order: concatenatedFields.length,
},
]
setConcatenatedFields(updatedFields)
form.setFieldsValue({ fieldToAdd: undefined })
}
// Move field up in order
const moveFieldUp = (index: number) => {
if (index <= 0) return
const newFields = [...concatenatedFields]
const temp = newFields[index]
newFields[index] = newFields[index - 1]
newFields[index - 1] = temp
// Update order property
newFields.forEach((field, idx) => {
field.order = idx
})
setConcatenatedFields(newFields)
}
// Move field down in order
const moveFieldDown = (index: number) => {
if (index >= concatenatedFields.length - 1) return
const newFields = [...concatenatedFields]
const temp = newFields[index]
newFields[index] = newFields[index + 1]
newFields[index + 1] = temp
// Update order property
newFields.forEach((field, idx) => {
field.order = idx
})
setConcatenatedFields(newFields)
}
// Remove field from list
const removeField = (index: number) => {
const newFields = concatenatedFields.filter((_, idx) => idx !== index)
// Update order property
newFields.forEach((field, idx) => {
field.order = idx
})
setConcatenatedFields(newFields)
}
// Steps definition
const steps = [
{
title: '请选择拼接字段',
content: (
<>
<Form.Item label="拼接新字段名称" name="name" rules={[{ required: true, message: '请输入字段名称' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Form.Item
label="拼接新字段英文名称"
name="english_name"
rules={[{ required: true, message: '请输入英文名称' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Form.Item
label="拼接新字段类型"
name="fieldType"
rules={[{ required: true, message: '请选择拼接新字段类型' }]}>
<Radio.Group options={[{ label: '文本', value: 'text' }]} />
</Form.Item>
<Form.Item
label="请选择数据拼接字段"
name="selectedFields"
rules={[
{
required: true,
message: '请添加至少一个拼接字段',
validator: () =>
concatenatedFields.length > 0 ? Promise.resolve() : Promise.reject('请添加至少一个拼接字段'),
},
]}>
<div>
<Flex gap={10}>
<Form.Item name="fieldToAdd" noStyle>
<Select
placeholder="选择要添加的字段"
options={fields.map((item) => ({
label: `${item.name} (${item.english_name})`,
value: item.english_name,
}))}
/>
</Form.Item>
<Button type="primary" onClick={addConcatenationField}>
添加拼接字段
</Button>
</Flex>
{concatenatedFields.map((item, index) => {
const fieldInfo = fields.find((f) => f.english_name === item.field)
return (
<Flex key={index} gap={10} style={{ marginTop: '10px' }}>
<div style={{ flex: 1, border: '1px solid #d9d9d9', padding: '4px 11px', borderRadius: '6px' }}>
{fieldInfo ? `${fieldInfo.name} (${fieldInfo.english_name})` : item.field}
</div>
<Button type="text" disabled={index === 0} onClick={() => moveFieldUp(index)}>
上移
</Button>
<Button
type="text"
disabled={index === concatenatedFields.length - 1}
onClick={() => moveFieldDown(index)}>
下移
</Button>
<Button type="text" danger onClick={() => removeField(index)}>
删除
</Button>
</Flex>
)
})}
</div>
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart} disabled={step >= 0}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: (
<>
第一步
<br />
新增字段
</>
),
},
{
title: (
<>
第二步
<br />
数据拼接
</>
),
},
{
title: (
<>
第三步
<br />
处理结果
</>
),
description: (
<>
累计处理{concatenatedFields.length}个字段
<br />
累计处理{data.list?.length || 0}条记录
</>
),
},
]}
/>
</Flex>
</>
),
},
]
// Handle next button logic
const handleNext = async () => {
try {
if (current === 0) {
// Validate the first step form
await form.validateFields(['name', 'english_name', 'fieldType', 'selectedFields'])
}
setCurrent(current + 1)
} catch (error) {
// Form validation error handling
console.error('表单验证失败', error)
}
}
// Reset everything when modal closes
const handleCancel = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
setConcatenatedFields([])
form.resetFields()
}
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
数据拼接
</Button>
<Modal
title={steps[current]?.title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleCancel}>
关闭
</Button>
)}
</Flex>
}
destroyOnClose
width={800}
onCancel={handleCancel}>
<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>
</>
)
}
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 { useState } from 'react'
import { Button, Flex, Modal, Radio, Form, Row, Col } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
export default function ButtonModal() {
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const initialValues = {
checked: '',
rule: '1',
}
const checked = Form.useWatch('checked', form)
const ruleOptions = [
{ label: '分号“;”', value: '1' },
{ label: '逗号“,”', value: '2' },
{ label: '空格“ ”', value: '3' },
// { label: '特定字符', value: '4' },
// { label: '前几个字符', value: '5' },
]
const [step, setStep] = useState<number>(-1)
const steps = [
{
title: '请选择数据拆分字段',
content: (
<Form.Item name="checked" rules={[{ required: true, message: '请选择数据拆分字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={6} 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 label="处理规则" name="rule" rules={[{ required: true, message: '请选择处理规则' }]}>
<Radio.Group options={ruleOptions} />
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<p>数据拆分处理字段:{checked}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(3)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: (
<>
第一步
<br />
计算拆分字段
</>
),
},
{
title: (
<>
第二步
<br />
数据库表增加拆分字段
</>
),
},
{
title: (
<>
第三步
<br />
更新拆分字段
</>
),
},
{
title: (
<>
第四步
<br />
更新原始字段
</>
),
},
{
title: (
<>
第五步
<br />
处理结果
</>
),
},
]}
/>
</Flex>
</>
),
},
]
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
数据拆分
</Button>
<Modal
title={steps[current].title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked}>
下一步
</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} initialValues={initialValues}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
</div>
</Modal>
</>
)
}
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 ( return <DataWrap title="数据预处理:数据拆分" buttons={<ButtonModal />}></DataWrap>
<DataWrap
title="数据预处理:数据拆分"
buttons={
<>
<Button type="primary">数据拆分</Button>
</>
}></DataWrap>
)
} }
import { useState } from 'react'
import { Button, Flex, Modal, Radio, Form, Row, Col, Input } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
export default function ButtonModal() {
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const initialValues = {
checked: '',
rule: '',
}
const checked = Form.useWatch('checked', form)
const [step, setStep] = useState<number>(-1)
const steps = [
{
title: '请选择去标点字段',
content: (
<Form.Item name="checked" rules={[{ required: true, message: '请选择去标点字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={6} 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 label="处理规则" name="rule" rules={[{ required: true, message: '请输入处理规则' }]}>
<Input />
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<p>数据去标点处理字段:{checked}</p>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: (
<>
第一步
<br />
开始
</>
),
},
{
title: (
<>
第二步
<br />
数据去标点处理
</>
),
},
{
title: (
<>
第三步
<br />
处理结果
</>
),
},
]}
/>
</Flex>
</>
),
},
]
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
数据去标点
</Button>
<Modal
title={steps[current].title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)} disabled={!checked}>
下一步
</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} initialValues={initialValues}>
{steps.map((item, index) => (
<div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content}
</div>
))}
</Form>
</div>
</Modal>
</>
)
}
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 ( return <DataWrap title="数据预处理:数据去标点" buttons={<ButtonModal />}></DataWrap>
<DataWrap
title="数据预处理:数据去标点"
buttons={
<>
<Button type="primary">数据去标点</Button>
</>
}></DataWrap>
)
} }
import { useEffect, useState } from 'react'
import { Button, Flex, Modal, Form, Table, Select } from 'antd'
import { useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
export default function ButtonModal() {
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const [dataSource, setDataSource] = useState<{ key: number; raw_value: string; new_value: string }[]>([])
const [step, setStep] = useState<number>(-1)
useEffect(() => {
if (fields?.length) {
setDataSource(
fields
.filter((item) => !item.type.includes('VARCHAR'))
.map((item: any, index) => ({
key: index + 1,
...item,
new_value: '',
}))
)
}
}, [fields])
// 处理映射值变化
const handleValueChange = (value: string, key: number) => {
setDataSource((prevDataSource) =>
prevDataSource.map((item) => (item.key === key ? { ...item, new_value: value } : item))
)
}
const options = [
{
label: '文本',
value: 'text',
},
]
const steps = [
{
title: '请选择转换字段',
content: (
<Form.Item>
<Table
bordered
pagination={false}
rowSelection={{ type: 'radio' }}
columns={[
{ title: '序号', dataIndex: 'key', align: 'center', width: 80 },
{ title: '字段名称', dataIndex: 'name', align: 'center' },
{ title: '原始值', dataIndex: 'type_name', align: 'center' },
{
title: '新数据类型',
dataIndex: 'new_value',
align: 'center',
render: (_, record) => (
<Select
options={options}
value={record.new_value}
placeholder="请选择"
onChange={(value) => handleValueChange(value, record.key)}></Select>
),
},
]}
dataSource={dataSource}
/>
</Form.Item>
),
},
{
title: '处理执行',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(1)}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: (
<>
第一步
<br />
开始
</>
),
},
{
title: (
<>
第二步
<br />
数据类型转换
</>
),
},
{
title: (
<>
第三步
<br />
处理结果
</>
),
},
]}
/>
</Flex>
</>
),
},
]
return (
<>
<Button type="primary" onClick={() => setOpen(true)}>
数据类型转换
</Button>
<Modal
title={steps[current].title}
open={open}
footer={
<Flex justify="center" gap={20}>
{current > 0 && <Button onClick={() => setCurrent(current - 1)}>上一步</Button>}
{current < steps.length - 1 && (
<Button type="primary" onClick={() => setCurrent(current + 1)}>
下一步
</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>
</>
)
}
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 { useEffect, useState } from 'react'
import { Button, Flex, Modal, Radio, Input, Form, Row, Col, Table, message } from 'antd'
import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps'
import { uniqBy } from 'lodash-es'
export default function ButtonModal() {
const { data = { list: [] } } = useDataQuery() // 添加默认值防止 data 为 undefined
const { data: fields = [] } = useDataFieldQuery()
const [open, setOpen] = useState(false)
const [current, setCurrent] = useState(0)
const [form] = Form.useForm()
const [dataSource, setDataSource] = useState<{ key: number; raw_value: string; mapping_value: string }[]>([])
const [step, setStep] = useState(-1)
// 使用 Form.useWatch 监听表单值变化
const checked = Form.useWatch('checked', form)
// 当 checked 或 data 变化时更新数据源
useEffect(() => {
if (checked && data.list?.length) {
const uniqList = uniqBy(data.list, checked)
setDataSource(
uniqList.map((item: any, index) => ({
key: index + 1,
raw_value: item[checked] || '',
mapping_value: '',
}))
)
}
}, [checked, data.list])
// 处理映射值变化
const handleMappingValueChange = (value: string, key: number) => {
setDataSource((prevDataSource) =>
prevDataSource.map((item) => (item.key === key ? { ...item, mapping_value: value } : item))
)
}
const handleStart = () => {
setStep(0)
// Simulate processing steps with timeouts
setTimeout(() => {
setStep(1)
setTimeout(() => {
setStep(4)
message.success('数据处理完成!')
}, 1000)
}, 1000)
}
// 步骤定义
const steps = [
{
title: '请选择数据分箱字段',
content: (
<>
<Form.Item label="数据分箱字段名称" name="name" rules={[{ required: true, message: '请输入字段名称' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Form.Item
label="数据分箱字段英文名称"
name="english_name"
rules={[{ required: true, message: '请输入英文名称' }]}>
<Input placeholder="请输入" />
</Form.Item>
<Form.Item
label="请选择数据分箱字段"
name="checked"
rules={[{ required: true, message: '请选择数据分箱字段' }]}>
<Radio.Group>
<Row gutter={[10, 10]}>
{fields.map((item) => (
<Col span={8} key={item.english_name}>
<Radio value={item.english_name}>{item.name}</Radio>
</Col>
))}
</Row>
</Radio.Group>
</Form.Item>
</>
),
},
{
title: '配置数据分箱规则',
content: (
<>
<Form.Item label="数据分箱操作字段">{checked}</Form.Item>
<Form.Item>
<Table
bordered
pagination={{ pageSize: 10 }}
columns={[
{ title: '序号', dataIndex: 'key', align: 'center', width: 80 },
{ title: '原始值', dataIndex: 'raw_value', align: 'center' },
{
title: '映射值',
dataIndex: 'mapping_value',
align: 'center',
render: (_, record) => (
<Input
value={record.mapping_value}
onChange={(e) => handleMappingValueChange(e.target.value, record.key)}
placeholder="请输入映射值"
/>
),
},
]}
dataSource={dataSource}
/>
</Form.Item>
</>
),
},
{
title: '处理执行',
content: (
<>
<Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={handleStart}>
开始处理
</Button>
<AppProgressSteps
style={{ margin: '80px' }}
current={step}
items={[
{
title: (
<>
第一步
<br />
新建字段
</>
),
},
{
title: (
<>
第二步
<br />
复制数据
</>
),
},
{
title: (
<>
第三步
<br />
数据分箱处理
</>
),
},
{
title: (
<>
第四步
<br />
处理结果
</>
),
description: (
<>
累计处理{dataSource.length}个字段
<br />
累计处理{data.list?.length || 0}条记录
</>
),
},
]}
/>
</Flex>
</>
),
},
]
// 处理下一步按钮逻辑
const handleNext = async () => {
try {
if (current === 0) {
// 第一步验证表单
await form.validateFields(['name', 'english_name', 'checked'])
}
setCurrent(current + 1)
} catch (error) {
// 表单验证错误处理
console.error('表单验证失败', error)
}
}
// 重置状态
const handleClose = () => {
setOpen(false)
setCurrent(0)
setStep(-1)
form.resetFields()
setDataSource([])
}
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={handleNext}>
下一步
</Button>
)}
{current === steps.length - 1 && (
<Button type="primary" onClick={handleClose}>
关闭
</Button>
)}
</Flex>
}
destroyOnClose
width={800}
onCancel={handleClose}>
<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>
</>
)
}
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 { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import { Button, Flex, Modal, Radio, Input, Form, Row, Col, Table } from 'antd' import { Button, Flex, Modal, Radio, Input, Form, Row, Col, Table, message } from 'antd'
import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery' import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery'
import AppProgressSteps from '@/components/AppProgressSteps' import AppProgressSteps from '@/components/AppProgressSteps'
import { uniqBy } from 'lodash-es' import { uniqBy } from 'lodash-es'
...@@ -38,6 +38,18 @@ export default function ButtonModal() { ...@@ -38,6 +38,18 @@ export default function ButtonModal() {
) )
} }
const handleStart = () => {
setStep(0)
// Simulate processing steps with timeouts
setTimeout(() => {
setStep(1)
setTimeout(() => {
setStep(4)
message.success('数据处理完成!')
}, 1000)
}, 1000)
}
// 步骤定义 // 步骤定义
const steps = [ const steps = [
{ {
...@@ -103,7 +115,7 @@ export default function ButtonModal() { ...@@ -103,7 +115,7 @@ export default function ButtonModal() {
content: ( content: (
<> <>
<Flex vertical align="center" style={{ marginTop: '20px' }}> <Flex vertical align="center" style={{ marginTop: '20px' }}>
<Button type="primary" onClick={() => setStep(2)}> <Button type="primary" onClick={handleStart} disabled={step >= 0}>
开始处理 开始处理
</Button> </Button>
<AppProgressSteps <AppProgressSteps
...@@ -214,7 +226,7 @@ export default function ButtonModal() { ...@@ -214,7 +226,7 @@ export default function ButtonModal() {
<div style={{ minHeight: 300, padding: '20px 0' }}> <div style={{ minHeight: 300, padding: '20px 0' }}>
<Form form={form} labelCol={{ span: 5 }} preserve={false}> <Form form={form} labelCol={{ span: 5 }} preserve={false}>
{steps.map((item, index) => ( {steps.map((item, index) => (
<div key={index} style={{ display: current === index ? 'block' : 'none', marginTop: '20px' }}> <div key={index} hidden={current !== index} style={{ marginTop: '20px' }}>
{item.content} {item.content}
</div> </div>
))} ))}
......
...@@ -7,7 +7,10 @@ import { useAI } from '@/hooks/useAI' ...@@ -7,7 +7,10 @@ import { useAI } from '@/hooks/useAI'
import prompt from '@/utils/prompt' import prompt from '@/utils/prompt'
export default function ButtonModal() { export default function ButtonModal() {
const [results, setResults] = useState<Array<Array<number>>>([]) const [results, setResults] = useState<Array<{ lines: number[]; desc: string }>>([
{ lines: [1, 3], desc: '第1行、第3行的数据完全一样' },
{ lines: [2, 8], desc: '第2行、第8行的数据完全一样' },
])
const { isLoading, post } = useAI({ const { isLoading, post } = useAI({
onComplete: (message) => { onComplete: (message) => {
...@@ -78,10 +81,9 @@ export default function ButtonModal() { ...@@ -78,10 +81,9 @@ export default function ButtonModal() {
<Flex justify="space-between" style={{ marginBottom: 20 }}> <Flex justify="space-between" style={{ marginBottom: 20 }}>
探索结果: 探索结果:
</Flex> </Flex>
{results.map((lines, index) => ( {results.map((item, index) => (
<p key={index}> <p key={index}>
{index + 1} {index + 1}{item.desc}
{lines.map((line) => `、第${line}行`)}的数据完全一样
</p> </p>
))} ))}
{!results.length && <Empty></Empty>} {!results.length && <Empty></Empty>}
......
...@@ -26,27 +26,27 @@ export const routes: RouteObject[] = [ ...@@ -26,27 +26,27 @@ 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/null/views/Index')) }, { path: 'preprocess/repeat', Component: lazy(() => import('./preprocess/repeat/views/Index')) },
{ path: 'preprocess/max', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/max', Component: lazy(() => import('./preprocess/max/views/Index')) },
{ path: 'preprocess/min', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/min', Component: lazy(() => import('./preprocess/min/views/Index')) },
{ path: 'preprocess/error', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/error', Component: lazy(() => import('./preprocess/error/views/Index')) },
{ path: 'preprocess/split', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/split', Component: lazy(() => import('./preprocess/split/views/Index')) },
{ path: 'preprocess/space', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/space', Component: lazy(() => import('./preprocess/space/views/Index')) },
{ path: 'preprocess/symbol', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/symbol', Component: lazy(() => import('./preprocess/symbol/views/Index')) },
{ path: 'preprocess/type', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/type', Component: lazy(() => import('./preprocess/type/views/Index')) },
{ path: 'preprocess/sort', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/sort', Component: lazy(() => import('./preprocess/sort/views/Index')) },
{ path: 'preprocess/splice', Component: lazy(() => import('./preprocess/null/views/Index')) }, { path: 'preprocess/splice', Component: lazy(() => import('./preprocess/splice/views/Index')) },
// 数据预处理 // 数据预处理
{ path: 'process', element: <Navigate to="mapping" /> }, { path: 'process', element: <Navigate to="mapping" /> },
{ path: 'process/mapping', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/mapping', Component: lazy(() => import('./process/mapping/views/Index')) },
{ path: 'process/binning', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/binning', Component: lazy(() => import('./process/binning/views/Index')) },
{ path: 'process/group', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/group', Component: lazy(() => import('./process/group/views/Index')) },
{ path: 'process/desensitization', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/desensitization', Component: lazy(() => import('./process/desensitization/views/Index')) },
{ path: 'process/date', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/date', Component: lazy(() => import('./process/date/views/Index')) },
{ path: 'process/string', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/string', Component: lazy(() => import('./process/string/views/Index')) },
{ path: 'process/number', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/number', Component: lazy(() => import('./process/number/views/Index')) },
{ path: 'process/logic', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/logic', Component: lazy(() => import('./process/logic/views/Index')) },
{ path: 'process/perspective', Component: lazy(() => import('./process/mapping/views/Index')) }, { path: 'process/perspective', Component: lazy(() => import('./process/perspective/views/Index')) },
// 数据挖掘 // 数据挖掘
{ 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')) },
......
const json = {
null: {
results: [
{ name: '字段1', key: 'name1', desc: 'A000001、A000002...' },
{ name: '字段2', key: 'name2', desc: 'A000001、A000002...' },
],
},
repeat: {
results: [
{ lines: [1, 3], desc: '第1行、第3行的数据完全一样' },
{ lines: [2, 8], desc: '第2行、第8行的数据完全一样' },
],
},
max: {
results: [
{ name: '字段1', key: 'name1', desc: 'XXXX值过大,参考XXXXXXXX' },
{ name: '字段2', key: 'name2', desc: 'XXXX值过大,参考XXXXXXXX' },
],
},
min: {
results: [
{ name: '字段1', key: 'name1', desc: 'XXXX值过小,参考XXXXXXXX' },
{ name: '字段2', key: 'name2', desc: 'XXXX值过小,参考XXXXXXXX' },
],
},
error: {
results: [{ name: '字段1', key: 'name1', desc: 'XXXX值存在逻辑错误,参考XXXXXXXX' }],
},
}
const prompt = { const prompt = {
// 缺失值处理 // 缺失值处理
null: `找出数据集中有缺失值的字段,并返回 JSON 格式的结果。返回内容仅包含缺失字段的名称(name)及其对应的数据有哪些,字段像主键的数据(desc)。如果没有缺失值,则返回空数组 []。 null: `找出数据集中有缺失值的字段,并返回 JSON 格式的结果。返回内容仅包含缺失字段的名称(name)及其对应的数据有哪些,字段像主键的数据(desc)。如果没有缺失值,则返回空数组 []。
返回格式示例: 返回格式示例:
json json
{ ${json.null}
"results": [
{"name": "字段1", "desc": "A000001、A000002..."},
{"name": "字段2", "desc": "A000001、A000002..."}
]
}
要求: 要求:
仅包含缺失值的字段(为空、null、undefined 等视为缺失)。 仅包含缺失值的字段(为空、null、undefined 等视为缺失)。
如果所有字段都有值,则返回 { "results": [] }。`, 如果所有字段都有值,则返回 { "results": [] }。`,
// 重复值处理 // 重复值处理
repeat: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有重复值数据的情况,即:所有字段的值出现完全相同的多条数据。如果存在,请告诉我。并返回 JSON 格式的结果。返回内容仅包重复数据所在的行,如果没有重复记录,则返回空数组 []。 repeat: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有重复值数据的情况,即:所有字段的值出现完全相同的多条数据。如果存在,请告诉我。并返回 JSON 格式的结果。返回内容仅包重复数据所在的行,如果没有重复记录,则返回空数组 []。
返回格式示例: 返回格式示例:
json json
{ ${json.repeat}
"results": [[1,11],[7,12,13]]
}
要求: 要求:
如果没有重复数据,则返回 { "results": [] }。`, 如果没有重复数据,则返回 { "results": [] }。`,
// 最大值处理 // 最大值处理
max: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有违反常规或者疑似不正常的过大值的情况。如果存在,请告诉我。 max: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有违反常规或者疑似不正常的过大值的情况。如果存在,请告诉我。
返回格式示例: 返回格式示例:
json json
{ ${json.max}
"results": [{name: '字段1', desc: 'XXXX值过大,参考XXXXXXXX}]
}
要求: 要求:
如果没有重复数据,则返回 { "results": [] }。`, 如果没有重复数据,则返回 { "results": [] }。`,
// 最小值处理 // 最小值处理
min: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有违反常规或者疑似不正常的过小值的情况。如果存在,请告诉我。 min: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有违反常规或者疑似不正常的过小值的情况。如果存在,请告诉我。
返回格式示例: 返回格式示例:
json json
{ ${json.min}
"results": [{name: '字段1', desc: 'XXXX值过小,参考XXXXXXXX}]
}
要求: 要求:
如果没有重复数据,则返回 { "results": [] }。`, 如果没有重复数据,则返回 { "results": [] }。`,
// 逻辑错误处理 // 逻辑错误处理
error: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有违反常规或者疑似不正常的逻辑错误的情况。如果存在,请告诉我。 error: `请根据我给你的数据集,帮我检查这个数据集里面是否存在有违反常规或者疑似不正常的逻辑错误的情况。如果存在,请告诉我。
返回格式示例: 返回格式示例:
json json
{ ${json.error}
"results": [{name: '字段1', desc: 'XXXX值存在逻辑错误,参考XXXXXXXX}]
}
要求: 要求:
如果没有重复数据,则返回 { "results": [] }。`, 如果没有重复数据,则返回 { "results": [] }。`,
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论