diff --git a/package.json b/package.json
index 54d61b3..ccdde02 100644
--- a/package.json
+++ b/package.json
@@ -16,6 +16,7 @@
},
"dependencies": {
"@tailwindcss/postcss": "^4.3.3",
+ "echarts": "^6.1.0",
"element-plus": "^2.14.4",
"pinia": "^4.0.2",
"postcss": "^8.5.26",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index ef43d4f..c6de514 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -11,6 +11,9 @@ importers:
'@tailwindcss/postcss':
specifier: ^4.3.3
version: 4.3.3
+ echarts:
+ specifier: ^6.1.0
+ version: 6.1.0
element-plus:
specifier: ^2.14.4
version: 2.14.4(vue@3.5.41(typescript@6.0.3))
@@ -1076,6 +1079,9 @@ packages:
resolution: {integrity: sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==}
engines: {node: '>=8'}
+ echarts@6.1.0:
+ resolution: {integrity: sha512-q0yaFPggC9FUdsWH4blavRWFmxdrIodbkoKNAjJudAI6CA9gNPxHtV2RcZNEepZVlk4yvBYkOkbk6HIVpIyHZA==}
+
electron-to-chromium@1.5.406:
resolution: {integrity: sha512-hWH5ORBi3d0IipnMh7BN5GDTaAmrSSSWmznwt2zltdiRNEWoEQyTwF0FFSBxzHO7hLSRT6loQu3IQGV0wg/Tvg==}
@@ -1823,6 +1829,9 @@ packages:
peerDependencies:
typescript: '>=4.8.4'
+ tslib@2.3.0:
+ resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
+
type-check@0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
engines: {node: '>= 0.8.0'}
@@ -2101,6 +2110,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
+ zrender@6.1.0:
+ resolution: {integrity: sha512-oEGMDB6pOP2S6OwRR4PdVv610zrjnA3Bh+JnSG12fYJlBKjtNAoEb5fSUoCOOINlH96I2fU38/A2UpRKs67xYQ==}
+
snapshots:
'@alloc/quick-lru@5.2.0': {}
@@ -3051,6 +3063,11 @@ snapshots:
detect-libc@2.1.2: {}
+ echarts@6.1.0:
+ dependencies:
+ tslib: 2.3.0
+ zrender: 6.1.0
+
electron-to-chromium@1.5.406: {}
element-plus@2.14.4(vue@3.5.41(typescript@6.0.3)):
@@ -3753,6 +3770,8 @@ snapshots:
dependencies:
typescript: 6.0.3
+ tslib@2.3.0: {}
+
type-check@0.4.0:
dependencies:
prelude-ls: 1.2.1
@@ -4044,3 +4063,7 @@ snapshots:
yaml@2.9.0: {}
yocto-queue@0.1.0: {}
+
+ zrender@6.1.0:
+ dependencies:
+ tslib: 2.3.0
diff --git a/src/editor/panels/material/components/MaterialItem.vue b/src/editor/panels/material/components/MaterialItem.vue
index af58bb4..f0476c2 100644
--- a/src/editor/panels/material/components/MaterialItem.vue
+++ b/src/editor/panels/material/components/MaterialItem.vue
@@ -18,7 +18,9 @@ function onStart(event: DragEvent) {
@dragstart="onStart"
>
{{ props.material.name }}
-
+
+
+
diff --git a/src/editor/panels/property/components/FormCreate.vue b/src/editor/panels/property/components/FormCreate.vue
index 6f52c30..7dff75b 100644
--- a/src/editor/panels/property/components/FormCreate.vue
+++ b/src/editor/panels/property/components/FormCreate.vue
@@ -1,6 +1,6 @@
@@ -21,6 +23,7 @@ const componentMap: Record = {
applyChange(formData, setter.key, value)"
@focus="startBatch()"
@blur="commitBatch()"
diff --git a/src/editor/panels/property/components/NodeProperty.vue b/src/editor/panels/property/components/NodeProperty.vue
index 1d561f5..9855178 100644
--- a/src/editor/panels/property/components/NodeProperty.vue
+++ b/src/editor/panels/property/components/NodeProperty.vue
@@ -11,7 +11,12 @@ defineOptions({
const editorStore = useEditorStore()
const { selectedNode } = storeToRefs(editorStore)
-const setters = getMaterialSetters(selectedNode.value?.type || '') ?? []
+const setters = computed(() => {
+ return getMaterialSetters(selectedNode.value?.type || '') ?? []
+})
+
+// 属性分组默认全部展开
+const activeNames = ref(['layout', 'component'])
// 布局属性
const layoutSetters = [
@@ -40,11 +45,11 @@ const layoutSetters = [
-
-
+
+
-
+
diff --git a/src/materials/charts/area.ts b/src/materials/charts/area.ts
new file mode 100644
index 0000000..3b1fd34
--- /dev/null
+++ b/src/materials/charts/area.ts
@@ -0,0 +1,179 @@
+import type { MaterialDefinition } from '@/schema/materials'
+
+export const areaMaterial: MaterialDefinition = {
+ name: '面积图',
+ group: 'charts',
+ icon: 'solar:graph-new-bold',
+ setters: [
+ {
+ type: 'input',
+ label: '标题',
+ key: 'props.option.title.text',
+ },
+ {
+ type: 'color',
+ label: '标题色',
+ key: 'props.option.title.textStyle.color',
+ },
+ {
+ type: 'checkbox',
+ label: '图例显示',
+ key: 'props.option.legend.show',
+ },
+ {
+ type: 'select',
+ label: '对齐',
+ key: 'props.option.title.left',
+ props: {
+ options: [
+ { label: '左对齐', value: 'left' },
+ { label: '居中', value: 'center' },
+ { label: '右对齐', value: 'right' },
+ ],
+ },
+ },
+ {
+ type: 'color',
+ label: '线颜色',
+ key: 'props.option.series.0.lineStyle.color',
+ },
+ {
+ type: 'color',
+ label: '面积色',
+ key: 'props.option.series.0.areaStyle.color',
+ },
+ {
+ type: 'input',
+ label: 'X字段',
+ key: 'props.option.series.0.encode.x',
+ },
+ {
+ type: 'input',
+ label: 'Y字段',
+ key: 'props.option.series.0.encode.y',
+ },
+ {
+ type: 'number',
+ label: '上边距',
+ key: 'props.option.grid.top',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '右边距',
+ key: 'props.option.grid.right',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '下边距',
+ key: 'props.option.grid.bottom',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '左边距',
+ key: 'props.option.grid.left',
+ span: 12,
+ },
+ ],
+ schema: {
+ type: 'area-chart',
+ name: '面积图',
+ layout: {
+ x: 0,
+ y: 0,
+ width: 400,
+ height: 260,
+ },
+ props: {
+ option: {
+ legend: {
+ top: 38,
+ left: 'center',
+ itemWidth: 12,
+ itemHeight: 8,
+ show: true,
+ textStyle: {
+ color: '#cbd5e1',
+ },
+ },
+ title: {
+ text: '成交额趋势',
+ top: 8,
+ left: 'center',
+ textStyle: {
+ color: '#ffffff',
+ fontSize: 16,
+ },
+ },
+ tooltip: {
+ trigger: 'axis',
+ },
+ dataset: {
+ source: [
+ { date: '周一', revenue: 120 },
+ { date: '周二', revenue: 200 },
+ { date: '周三', revenue: 150 },
+ { date: '周四', revenue: 260 },
+ { date: '周五', revenue: 330 },
+ { date: '周六', revenue: 420 },
+ { date: '周日', revenue: 510 },
+ ],
+ },
+ grid: {
+ top: 86,
+ right: 24,
+ bottom: 32,
+ left: 48,
+ containLabel: true,
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ axisLine: {
+ lineStyle: {
+ color: '#64748b',
+ },
+ },
+ axisLabel: {
+ color: '#cbd5e1',
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: {
+ color: '#cbd5e1',
+ },
+ splitLine: {
+ lineStyle: {
+ color: 'rgba(148, 163, 184, 0.18)',
+ },
+ },
+ },
+ series: [
+ {
+ name: '成交额',
+ type: 'line',
+ smooth: true,
+ symbolSize: 8,
+ encode: {
+ x: 'date',
+ y: 'revenue',
+ },
+ lineStyle: {
+ width: 3,
+ color: '#22d3ee',
+ },
+ itemStyle: {
+ color: '#22d3ee',
+ },
+ areaStyle: {
+ color: 'rgba(34, 211, 238, 0.25)',
+ },
+ },
+ ],
+ },
+ },
+ },
+}
diff --git a/src/materials/charts/bar.ts b/src/materials/charts/bar.ts
new file mode 100644
index 0000000..5f39175
--- /dev/null
+++ b/src/materials/charts/bar.ts
@@ -0,0 +1,163 @@
+import type { MaterialDefinition } from '@/schema/materials'
+
+export const barMaterial: MaterialDefinition = {
+ name: '柱状图',
+ group: 'charts',
+ icon: 'solar:chart-2-bold',
+ setters: [
+ {
+ type: 'input',
+ label: '标题',
+ key: 'props.option.title.text',
+ },
+ {
+ type: 'color',
+ label: '标题色',
+ key: 'props.option.title.textStyle.color',
+ },
+ {
+ type: 'checkbox',
+ label: '图例显示',
+ key: 'props.option.legend.show',
+ },
+ {
+ type: 'select',
+ label: '对齐',
+ key: 'props.option.title.left',
+ props: {
+ options: [
+ { label: '左对齐', value: 'left' },
+ { label: '居中', value: 'center' },
+ { label: '右对齐', value: 'right' },
+ ],
+ },
+ },
+ {
+ type: 'color',
+ label: '柱颜色',
+ key: 'props.option.series.0.itemStyle.color',
+ },
+ {
+ type: 'input',
+ label: 'X字段',
+ key: 'props.option.series.0.encode.x',
+ },
+ {
+ type: 'input',
+ label: 'Y字段',
+ key: 'props.option.series.0.encode.y',
+ },
+ {
+ type: 'number',
+ label: '上边距',
+ key: 'props.option.grid.top',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '右边距',
+ key: 'props.option.grid.right',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '下边距',
+ key: 'props.option.grid.bottom',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '左边距',
+ key: 'props.option.grid.left',
+ span: 12,
+ },
+ ],
+ schema: {
+ type: 'bar-chart',
+ name: '柱状图',
+ layout: {
+ x: 0,
+ y: 0,
+ width: 400,
+ height: 260,
+ },
+ props: {
+ option: {
+ legend: {
+ top: 38,
+ left: 'center',
+ itemWidth: 12,
+ itemHeight: 8,
+ show: true,
+ textStyle: {
+ color: '#cbd5e1',
+ },
+ },
+ title: {
+ text: '销售额统计',
+ top: 8,
+ left: 'center',
+ textStyle: {
+ color: '#ffffff',
+ fontSize: 16,
+ },
+ },
+ tooltip: {},
+ dataset: {
+ source: [
+ { month: '一月', sales: 120 },
+ { month: '二月', sales: 200 },
+ { month: '三月', sales: 150 },
+ { month: '四月', sales: 80 },
+ { month: '五月', sales: 170 },
+ { month: '六月', sales: 240 },
+ ],
+ },
+ grid: {
+ top: 86,
+ right: 24,
+ bottom: 32,
+ left: 48,
+ containLabel: true,
+ },
+ xAxis: {
+ type: 'category',
+ axisLine: {
+ lineStyle: {
+ color: '#64748b',
+ },
+ },
+ axisLabel: {
+ color: '#cbd5e1',
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: {
+ color: '#cbd5e1',
+ },
+ splitLine: {
+ lineStyle: {
+ color: 'rgba(148, 163, 184, 0.18)',
+ },
+ },
+ },
+ series: [
+ {
+ name: '销售额',
+ type: 'bar',
+ barWidth: '45%',
+ encode: {
+ x: 'month',
+ y: 'sales',
+ },
+ itemStyle: {
+ color: '#22d3ee',
+ borderRadius: [4, 4, 0, 0],
+ },
+ },
+ ],
+ },
+ },
+ },
+}
diff --git a/src/materials/charts/component.vue b/src/materials/charts/component.vue
new file mode 100644
index 0000000..53bd0f5
--- /dev/null
+++ b/src/materials/charts/component.vue
@@ -0,0 +1,50 @@
+
+
+
+
+
+
+
+
diff --git a/src/materials/charts/index.ts b/src/materials/charts/index.ts
index 410e0ea..2526fe1 100644
--- a/src/materials/charts/index.ts
+++ b/src/materials/charts/index.ts
@@ -1,26 +1,17 @@
import type { MaterialDefinition } from '@/schema/materials'
+import ChartMaterial from './component.vue'
+import { barMaterial } from './bar'
+import { areaMaterial } from './area'
+import { lineMaterial } from './line'
+import { pieMaterial } from './pie'
-export const chartsMaterial: MaterialDefinition = {
- name: '柱状图',
- icon: '',
- group: 'charts',
- setters: [],
- schema: {
- type: 'chart',
- name: '柱状图',
- layout: {
- x: 0,
- y: 0,
- width: 400,
- height: 300,
- },
- props: {
- data: [],
- },
- },
-}
-
-export function install(register: (material: MaterialDefinition) => void) {
+export function install(register: (material: MaterialDefinition, component: Component) => void) {
// 注册柱状图物料
- register(chartsMaterial)
+ register(barMaterial, ChartMaterial)
+ // 注册面积图物料
+ register(areaMaterial, ChartMaterial)
+ // 注册折线图物料
+ register(lineMaterial, ChartMaterial)
+ // 注册饼图物料
+ register(pieMaterial, ChartMaterial)
}
diff --git a/src/materials/charts/line.ts b/src/materials/charts/line.ts
new file mode 100644
index 0000000..70be6aa
--- /dev/null
+++ b/src/materials/charts/line.ts
@@ -0,0 +1,171 @@
+import type { MaterialDefinition } from '@/schema/materials'
+
+export const lineMaterial: MaterialDefinition = {
+ name: '折线图',
+ group: 'charts',
+ icon: 'solar:graph-up-bold',
+ setters: [
+ {
+ type: 'input',
+ label: '标题',
+ key: 'props.option.title.text',
+ },
+ {
+ type: 'color',
+ label: '标题色',
+ key: 'props.option.title.textStyle.color',
+ },
+ {
+ type: 'checkbox',
+ label: '图例显示',
+ key: 'props.option.legend.show',
+ },
+ {
+ type: 'select',
+ label: '对齐',
+ key: 'props.option.title.left',
+ props: {
+ options: [
+ { label: '左对齐', value: 'left' },
+ { label: '居中', value: 'center' },
+ { label: '右对齐', value: 'right' },
+ ],
+ },
+ },
+ {
+ type: 'color',
+ label: '线颜色',
+ key: 'props.option.series.0.lineStyle.color',
+ },
+ {
+ type: 'input',
+ label: 'X字段',
+ key: 'props.option.series.0.encode.x',
+ },
+ {
+ type: 'input',
+ label: 'Y字段',
+ key: 'props.option.series.0.encode.y',
+ },
+ {
+ type: 'number',
+ label: '上边距',
+ key: 'props.option.grid.top',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '右边距',
+ key: 'props.option.grid.right',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '下边距',
+ key: 'props.option.grid.bottom',
+ span: 12,
+ },
+ {
+ type: 'number',
+ label: '左边距',
+ key: 'props.option.grid.left',
+ span: 12,
+ },
+ ],
+ schema: {
+ type: 'line-chart',
+ name: '折线图',
+ layout: {
+ x: 0,
+ y: 0,
+ width: 400,
+ height: 260,
+ },
+ props: {
+ option: {
+ legend: {
+ top: 38,
+ left: 'center',
+ itemWidth: 12,
+ itemHeight: 8,
+ show: true,
+ textStyle: {
+ color: '#cbd5e1',
+ },
+ },
+ title: {
+ text: '访问量趋势',
+ top: 8,
+ left: 'center',
+ textStyle: {
+ color: '#ffffff',
+ fontSize: 16,
+ },
+ },
+ tooltip: {
+ trigger: 'axis',
+ },
+ dataset: {
+ source: [
+ { date: '周一', visits: 820 },
+ { date: '周二', visits: 932 },
+ { date: '周三', visits: 901 },
+ { date: '周四', visits: 934 },
+ { date: '周五', visits: 1290 },
+ { date: '周六', visits: 1330 },
+ { date: '周日', visits: 1320 },
+ ],
+ },
+ grid: {
+ top: 86,
+ right: 24,
+ bottom: 32,
+ left: 48,
+ containLabel: true,
+ },
+ xAxis: {
+ type: 'category',
+ boundaryGap: false,
+ axisLine: {
+ lineStyle: {
+ color: '#64748b',
+ },
+ },
+ axisLabel: {
+ color: '#cbd5e1',
+ },
+ },
+ yAxis: {
+ type: 'value',
+ axisLabel: {
+ color: '#cbd5e1',
+ },
+ splitLine: {
+ lineStyle: {
+ color: 'rgba(148, 163, 184, 0.18)',
+ },
+ },
+ },
+ series: [
+ {
+ name: '访问量',
+ type: 'line',
+ smooth: true,
+ symbolSize: 8,
+ encode: {
+ x: 'date',
+ y: 'visits',
+ },
+ lineStyle: {
+ width: 3,
+ color: '#38bdf8',
+ },
+ itemStyle: {
+ color: '#38bdf8',
+ },
+ },
+ ],
+ },
+ },
+ },
+}
diff --git a/src/materials/charts/pie.ts b/src/materials/charts/pie.ts
new file mode 100644
index 0000000..57003ba
--- /dev/null
+++ b/src/materials/charts/pie.ts
@@ -0,0 +1,116 @@
+import type { MaterialDefinition } from '@/schema/materials'
+
+export const pieMaterial: MaterialDefinition = {
+ name: '饼图',
+ group: 'charts',
+ icon: 'solar:pie-chart-2-bold',
+ setters: [
+ {
+ type: 'input',
+ label: '标题',
+ key: 'props.option.title.text',
+ },
+ {
+ type: 'color',
+ label: '标题色',
+ key: 'props.option.title.textStyle.color',
+ },
+ {
+ type: 'checkbox',
+ label: '图例显示',
+ key: 'props.option.legend.show',
+ },
+ {
+ type: 'select',
+ label: '对齐',
+ key: 'props.option.title.left',
+ props: {
+ options: [
+ { label: '左对齐', value: 'left' },
+ { label: '居中', value: 'center' },
+ { label: '右对齐', value: 'right' },
+ ],
+ },
+ },
+ {
+ type: 'color',
+ label: '主色',
+ key: 'props.option.color.0',
+ },
+ {
+ type: 'input',
+ label: '名称字段',
+ key: 'props.option.series.0.encode.itemName',
+ },
+ {
+ type: 'input',
+ label: '数值字段',
+ key: 'props.option.series.0.encode.value',
+ },
+ ],
+ schema: {
+ type: 'pie-chart',
+ name: '饼图',
+ layout: {
+ x: 0,
+ y: 0,
+ width: 400,
+ height: 260,
+ },
+ props: {
+ option: {
+ color: ['#22d3ee', '#a78bfa', '#f59e0b', '#34d399', '#fb7185'],
+ legend: {
+ top: 38,
+ left: 'center',
+ itemWidth: 12,
+ itemHeight: 8,
+ show: true,
+ textStyle: {
+ color: '#cbd5e1',
+ },
+ },
+ title: {
+ text: '访问来源占比',
+ top: 8,
+ left: 'center',
+ textStyle: {
+ color: '#ffffff',
+ fontSize: 16,
+ },
+ },
+ tooltip: {
+ trigger: 'item',
+ },
+ dataset: {
+ source: [
+ { channel: '搜索引擎', value: 1048 },
+ { channel: '直接访问', value: 735 },
+ { channel: '联盟广告', value: 484 },
+ { channel: '视频广告', value: 300 },
+ ],
+ },
+ series: [
+ {
+ name: '访问来源',
+ type: 'pie',
+ center: ['50%', '62%'],
+ avoidLabelOverlap: true,
+ label: {
+ color: '#e2e8f0',
+ },
+ labelLine: {
+ lineStyle: {
+ color: '#94a3b8',
+ },
+ },
+ encode: {
+ itemName: 'channel',
+ value: 'value',
+ },
+ },
+ ],
+ },
+ },
+ },
+}
diff --git a/src/materials/text/index.ts b/src/materials/text/index.ts
index d69c7a6..2ad35c5 100644
--- a/src/materials/text/index.ts
+++ b/src/materials/text/index.ts
@@ -3,7 +3,7 @@ import TextMaterial from './component.vue'
const textMaterial: MaterialDefinition = {
name: '文本',
- icon: '',
+ icon: 'solar:text-bold',
group: 'info',
setters: [
{