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

chore: update

上级 9ac109b8
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"echarts-for-react": "^3.0.2", "echarts-for-react": "^3.0.2",
"echarts-wordcloud": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lucide-react": "^0.484.0", "lucide-react": "^0.484.0",
"react": "^18.3.1", "react": "^18.3.1",
...@@ -3659,6 +3660,15 @@ ...@@ -3659,6 +3660,15 @@
"react": "^15.0.0 || >=16.0.0" "react": "^15.0.0 || >=16.0.0"
} }
}, },
"node_modules/echarts-wordcloud": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/echarts-wordcloud/-/echarts-wordcloud-2.1.0.tgz",
"integrity": "sha512-Kt1JmbcROgb+3IMI48KZECK2AP5lG6bSsOEs+AsuwaWJxQom31RTNd6NFYI01E/YaI1PFZeueaupjlmzSQasjQ==",
"license": "ISC",
"peerDependencies": {
"echarts": "^5.0.1"
}
},
"node_modules/echarts/node_modules/tslib": { "node_modules/echarts/node_modules/tslib": {
"version": "2.3.0", "version": "2.3.0",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz",
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
"blueimp-md5": "^2.19.0", "blueimp-md5": "^2.19.0",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"echarts-for-react": "^3.0.2", "echarts-for-react": "^3.0.2",
"echarts-wordcloud": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"lucide-react": "^0.484.0", "lucide-react": "^0.484.0",
"react": "^18.3.1", "react": "^18.3.1",
......
...@@ -2,6 +2,7 @@ import ReactECharts from 'echarts-for-react' ...@@ -2,6 +2,7 @@ import ReactECharts from 'echarts-for-react'
import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery' import { useDataQuery, useDataFieldQuery } from '@/hooks/useQuery'
import { merge } from 'lodash-es' import { merge } from 'lodash-es'
import { Table } from 'antd' import { Table } from 'antd'
import 'echarts-wordcloud'
const usePattern = (type = 'horizontal', color = '#5470C6') => { const usePattern = (type = 'horizontal', color = '#5470C6') => {
const createPattern = () => { const createPattern = () => {
...@@ -61,11 +62,11 @@ export default function Chart({ ...@@ -61,11 +62,11 @@ export default function Chart({
const { getFieldName } = useDataFieldQuery() const { getFieldName } = useDataFieldQuery()
const { image, repeat } = usePattern(fillPattern) const { image, repeat } = usePattern(fillPattern)
const itemStyleColor = fillPattern === 'solid' ? color : { image, repeat } const itemStyleColor = fillPattern === 'solid' ? color : { image, repeat }
if (!yField) { if (!(yField && yField.length > 0)) {
return null return null
} }
const dataset = { dimensions: [xField, ...yField], source: data.list } const dataset = { dimensions: [xField, ...yField].filter(Boolean), source: data.list }
let defaultOptions: any = { let defaultOptions: any = {
legend: {}, legend: {},
tooltip: {}, tooltip: {},
...@@ -175,7 +176,7 @@ export default function Chart({ ...@@ -175,7 +176,7 @@ export default function Chart({
}) })
break break
// 气泡图 // 气泡图
case '6': case '6': {
defaultOptions = merge(defaultOptions, { defaultOptions = merge(defaultOptions, {
yAxis: { show: false }, yAxis: { show: false },
xAxis: { show: false }, xAxis: { show: false },
...@@ -187,62 +188,50 @@ export default function Chart({ ...@@ -187,62 +188,50 @@ export default function Chart({
return '' return ''
}, },
}, },
series: yField.map((field) => ({ series: yField.map((field) => {
const maxVal = Math.max(...data.list.map((item: any) => item[field]))
const minVal = Math.min(...data.list.map((item: any) => item[field]))
return {
type: 'graph', type: 'graph',
layout: 'force', layout: 'force',
roam: true, roam: true,
label: {
show: true,
position: 'right',
formatter: '{b}',
},
force: { force: {
repulsion: 100, repulsion: 150,
edgeLength: 30, gravity: 0.05,
gravity: 0.1, edgeLength: 20,
},
emphasis: {
focus: 'self',
label: {
show: true,
fontSize: 14,
},
}, },
data: data.list.map((item: any) => { data: data.list.map((item: any) => {
const size = 20 + ((parseFloat(item[field]) - minVal) / (maxVal - minVal || 1)) * 60 // 字体大小映射
const value = item[field] || 10 const value = item[field] || 10
const name = item[xField] const name = item[xField]
return { name, value } return {
name,
value,
symbolSize: size,
label: {
show: !!labelField,
position: 'inside',
fontSize: size / 2.5,
formatter: (params: any) => data.list[params.dataIndex][labelField],
},
}
}),
}
}), }),
})),
}) })
break break
}
// 词云 // 词云
case '7': case '7':
defaultOptions = merge(defaultOptions, { defaultOptions = merge(defaultOptions, {
tooltip: { show: true },
series: [ series: [
{ {
type: 'wordCloud', type: 'wordCloud',
shape: 'circle', shape: 'circle',
sizeRange: [12, 60], data: data.list.map((item: any) => ({
rotationRange: [-90, 90], name: item[labelField],
textStyle: { value: item[yField[0]],
color: () => })),
'rgb(' +
[
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
Math.round(Math.random() * 160),
].join(',') +
')',
},
emphasis: {
focus: 'self',
textStyle: {
shadowBlur: 10,
shadowColor: '#333',
},
},
}, },
], ],
}) })
...@@ -252,71 +241,33 @@ export default function Chart({ ...@@ -252,71 +241,33 @@ export default function Chart({
defaultOptions.series = [{ type: 'map' }] defaultOptions.series = [{ type: 'map' }]
break break
// 指标卡 // 指标卡
case '9': case '9': {
const count = data.list.reduce((acc: any, item: any) => acc + parseFloat(item[yField[0]]), 0).toFixed(2)
defaultOptions = merge(defaultOptions, { defaultOptions = merge(defaultOptions, {
tooltip: { graphic: {
formatter: '{a} <br/>{b} : {c}%', elements: [
},
series: [
{ {
type: 'gauge', type: 'text',
name: getFieldName(yField[0]), left: 'center',
detail: { formatter: '{value}%' }, top: 'middle',
axisLine: { style: {
lineStyle: { text: count,
width: 10, fontSize: 36,
color: [ fontWeight: 'bold',
[0.3, '#fd666d'], fill: color,
[0.7, '#37a2da'],
[1, '#67e0e3'],
],
},
},
pointer: {
itemStyle: {
color: 'auto',
},
},
axisTick: {
distance: -10,
length: 8,
lineStyle: {
color: '#fff',
width: 2,
},
},
splitLine: {
distance: -10,
length: 10,
lineStyle: {
color: '#fff',
width: 4,
},
},
axisLabel: {
color: 'inherit',
distance: 20,
fontSize: 12,
},
title: {
offsetCenter: [0, '-20%'],
fontSize: 14,
}, },
}, },
], ],
},
}) })
break break
}
// 漏斗图 // 漏斗图
case '10': case '10': {
defaultOptions = merge(defaultOptions, { defaultOptions = merge(defaultOptions, {
dataset, dataset,
tooltip: { trigger: 'item', formatter: '{b} : {c}' }, xAxis: { show: false },
legend: { yAxis: { show: false },
show: true,
orient: 'vertical',
left: 'left',
data: data.list.map((item: any) => item[xField]),
},
series: [ series: [
{ {
type: 'funnel', type: 'funnel',
...@@ -332,53 +283,39 @@ export default function Chart({ ...@@ -332,53 +283,39 @@ export default function Chart({
sort: 'descending', sort: 'descending',
gap: 2, gap: 2,
label: { label: {
show: true, show: !!labelField,
position: 'inside', position: 'inside',
formatter: '{b}', formatter: (params: any) => data.list[params.dataIndex][labelField],
},
labelLine: {
length: 10,
lineStyle: { width: 1, type: 'solid' },
},
itemStyle: {
borderColor: '#fff',
borderWidth: 1,
},
emphasis: {
label: { fontSize: 20 },
}, },
}, },
], ],
}) })
break break
}
// 直方图 // 直方图
case '11': case '11':
defaultOptions = merge(defaultOptions, { defaultOptions = merge(defaultOptions, {
tooltip: { trigger: 'axis', axisPointer: { type: 'shadow' } }, dataset,
xAxis: { type: 'category' }, xAxis: { type: 'category' },
yAxis: { type: 'value', name: 'Frequency' }, series: yField.map((field) => ({
series: [
{
type: 'bar', type: 'bar',
name: `Histogram of ${getFieldName(yField[0])}`, name: getFieldName(field),
barWidth: '99.3%',
label: { label: {
show: !!labelField, show: !!labelField,
position: 'top', position: 'top',
formatter: (params: any) => data.list[params.dataIndex][labelField], formatter: (params: any) => {
console.log(params.dataIndex)
return data.list[params.dataIndex][labelField]
}, },
itemStyle: { color: itemStyleColor },
}, },
], itemStyle: { borderRadius, color: itemStyleColor },
})),
}) })
break break
// 表格 // 表格
case '12': { case '12': {
const columns = yField.map((field) => ({ const columns = yField.map((field) => ({ title: getFieldName(field), dataIndex: field }))
title: getFieldName(field), return <Table rowKey="pk_id" dataSource={data.list} columns={columns} />
dataIndex: field,
}))
return <Table dataSource={data.list} columns={columns} />
} }
// 帕累托图 // 帕累托图
case '13': { case '13': {
......
...@@ -59,6 +59,7 @@ const Step1 = ({ fieldOptions, getFieldOptions, type }: any) => { ...@@ -59,6 +59,7 @@ const Step1 = ({ fieldOptions, getFieldOptions, type }: any) => {
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
{!['11', '10'].includes(type) && (
<Row gutter={20}> <Row gutter={20}>
<Col span={8}> <Col span={8}>
<Form.Item label='请选择"维度"字段' name="x"> <Form.Item label='请选择"维度"字段' name="x">
...@@ -66,6 +67,7 @@ const Step1 = ({ fieldOptions, getFieldOptions, type }: any) => { ...@@ -66,6 +67,7 @@ const Step1 = ({ fieldOptions, getFieldOptions, type }: any) => {
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
)}
<Row gutter={20}> <Row gutter={20}>
<Col span={8}> <Col span={8}>
<Form.Item label="是否显示行轴" name="showX" hidden={!['1', '2'].includes(type)}> <Form.Item label="是否显示行轴" name="showX" hidden={!['1', '2'].includes(type)}>
...@@ -90,11 +92,13 @@ const Step2 = ({ fieldOptions, type, showTitle }: any) => { ...@@ -90,11 +92,13 @@ const Step2 = ({ fieldOptions, type, showTitle }: any) => {
辅助可视化设置 辅助可视化设置
</Divider> </Divider>
<Row gutter={20}> <Row gutter={20}>
{!['11'].includes(type) && (
<Col span={12}> <Col span={12}>
<Form.Item label='请选择"标签"字段' name="labelField"> <Form.Item label='请选择"标签"字段' name="labelField">
<Select options={fieldOptions} placeholder="请选择" allowClear></Select> <Select options={fieldOptions} placeholder="请选择" allowClear></Select>
</Form.Item> </Form.Item>
</Col> </Col>
)}
<Col span={12}> <Col span={12}>
<Form.Item label="请选择颜色规则" name="color"> <Form.Item label="请选择颜色规则" name="color">
<Radio.Group options={[{ label: '自动颜色', value: 'auto' }]}></Radio.Group> <Radio.Group options={[{ label: '自动颜色', value: 'auto' }]}></Radio.Group>
...@@ -130,7 +134,7 @@ const Step2 = ({ fieldOptions, type, showTitle }: any) => { ...@@ -130,7 +134,7 @@ const Step2 = ({ fieldOptions, type, showTitle }: any) => {
</Row> </Row>
<Row gutter={20}> <Row gutter={20}>
<Col span={12}> <Col span={12}>
<Form.Item label="是否显示图例" name="showLegend"> <Form.Item label="是否显示图例" name="showLegend" hidden={['11'].includes(type)}>
<Radio.Group options={showOptions}></Radio.Group> <Radio.Group options={showOptions}></Radio.Group>
</Form.Item> </Form.Item>
</Col> </Col>
...@@ -164,14 +168,119 @@ const TableStep = ({ fieldOptions }: any) => { ...@@ -164,14 +168,119 @@ const TableStep = ({ fieldOptions }: any) => {
) )
} }
const FormStep = ({ type, fieldOptions, getFieldOptions }: any) => { // 指标卡设置
const GaugeStep = ({ getFieldOptions, showTitle }: any) => {
return (
<>
<Divider orientation="left" orientationMargin="0">
辅助可视化设置
</Divider>
<Row gutter={20}>
<Col span={8}>
<Form.Item label='请选择"度量"字段' name="y">
<Select
options={getFieldOptions('number')}
placeholder="请选择"
mode="multiple"
allowClear
maxCount={1}></Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="计算规则" name="yRule">
<Select options={ruleOptions} placeholder="请选择"></Select>
</Form.Item>
</Col>
<Col span={8}>
<Form.Item label="请选择颜色规则" name="color">
<Radio.Group options={[{ label: '自动颜色', value: 'auto' }]}></Radio.Group>
</Form.Item>
</Col>
</Row>
<Flex>
<Form.Item label="是否有标题" name="showTitle">
<Radio.Group
options={[
{ label: '无', value: false },
{ label: '有', value: true },
]}></Radio.Group>
</Form.Item>
<Form.Item name="title" hidden={!showTitle}>
<Input placeholder="请输入" />
</Form.Item>
</Flex>
</>
)
}
// 词云设置
const WordCloudStep = ({ fieldOptions, getFieldOptions, showTitle }: any) => {
return (
<>
<Divider orientation="left" orientationMargin="0">
辅助可视化设置
</Divider>
<Row gutter={20}>
<Col span={12}>
<Form.Item label="大小" name="y" rules={[{ required: true, message: '请选择' }]}>
<Select
options={getFieldOptions('number')}
placeholder="请选择"
mode="multiple"
allowClear
maxCount={1}></Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="计算规则" name="yRule">
<Select options={ruleOptions} placeholder="请选择"></Select>
</Form.Item>
</Col>
</Row>
<Row gutter={20}>
<Col span={12}>
<Form.Item label='请选择"标签"字段' name="labelField" rules={[{ required: true, message: '请选择' }]}>
<Select options={fieldOptions} placeholder="请选择" allowClear></Select>
</Form.Item>
</Col>
<Col span={12}>
<Form.Item label="请选择颜色规则" name="color">
<Radio.Group options={[{ label: '自动颜色', value: 'auto' }]}></Radio.Group>
</Form.Item>
</Col>
</Row>
<Flex>
<Form.Item label="是否有标题" name="showTitle">
<Radio.Group
options={[
{ label: '无', value: false },
{ label: '有', value: true },
]}></Radio.Group>
</Form.Item>
<Form.Item name="title" hidden={!showTitle}>
<Input placeholder="请输入" />
</Form.Item>
</Flex>
</>
)
}
const FormStep = ({ type, fieldOptions, getFieldOptions, showTitle }: any) => {
if (type === '12') { if (type === '12') {
return <TableStep fieldOptions={fieldOptions} /> return <TableStep fieldOptions={fieldOptions} />
} else if (type === '9') {
return <GaugeStep fieldOptions={fieldOptions} getFieldOptions={getFieldOptions} type={type} showTitle={showTitle} />
} else if (type === '6' || type === '7') {
return (
<WordCloudStep fieldOptions={fieldOptions} getFieldOptions={getFieldOptions} type={type} showTitle={showTitle} />
)
} else { } else {
return ( return (
<> <>
<Step1 fieldOptions={fieldOptions} getFieldOptions={getFieldOptions} type={type} /> <Step1 fieldOptions={fieldOptions} getFieldOptions={getFieldOptions} type={type} />
<Step2 fieldOptions={fieldOptions} type={type} /> <Step2 fieldOptions={fieldOptions} type={type} showTitle={showTitle} />
</> </>
) )
} }
...@@ -318,7 +427,7 @@ const ModalContent = ({ setOpen, type, id = '' }: Props) => { ...@@ -318,7 +427,7 @@ const ModalContent = ({ setOpen, type, id = '' }: Props) => {
<Form.Item label="组件名称" name="name" rules={[{ required: true, message: '请输入组件名称' }]}> <Form.Item label="组件名称" name="name" rules={[{ required: true, message: '请输入组件名称' }]}>
<Input placeholder="请输入" /> <Input placeholder="请输入" />
</Form.Item> </Form.Item>
<FormStep type={type} fieldOptions={fieldOptions} getFieldOptions={getFieldOptions} /> <FormStep type={type} fieldOptions={fieldOptions} getFieldOptions={getFieldOptions} showTitle={showTitle} />
<Divider orientation="left" orientationMargin="0"> <Divider orientation="left" orientationMargin="0">
预览组件效果 预览组件效果
</Divider> </Divider>
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论