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

chore: update

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