feat: 新增了自定义组件和echarts使用demo

Re-1.0
咬轮猫 3 years ago
parent 3e2265877d
commit 4ae7311674

@ -10,9 +10,11 @@
"postinstall": "husky install"
},
"dependencies": {
"echarts": "^5.4.1",
"element-plus": "^2.2.9",
"pinia": "^2.0.16",
"vue": "^3.2.25",
"vue-echarts": "^6.5.1",
"vue-router": "4"
},
"devDependencies": {

@ -6,6 +6,7 @@ specifiers:
'@typescript-eslint/eslint-plugin': ^5.30.5
'@typescript-eslint/parser': ^5.30.5
'@vitejs/plugin-vue': ^2.3.3
echarts: ^5.4.1
element-plus: ^2.2.9
eslint: ^8.19.0
eslint-config-prettier: ^8.5.0
@ -22,15 +23,18 @@ specifiers:
vite-plugin-svg-icons: ^2.0.1
vite-plugin-windicss: ^1.8.6
vue: ^3.2.25
vue-echarts: ^6.5.1
vue-eslint-parser: ^9.0.3
vue-router: '4'
vue-tsc: ^0.34.7
windicss: ^3.5.6
dependencies:
echarts: 5.4.1
element-plus: 2.2.9_vue@3.2.37
pinia: 2.0.17_j6bzmzd4ujpabbp5objtwxyjp4
vue: 3.2.37
vue-echarts: 6.5.1_echarts@5.4.1+vue@3.2.37
vue-router: 4.1.1_vue@3.2.37
devDependencies:
@ -1377,6 +1381,13 @@ packages:
is-obj: 2.0.0
dev: true
/echarts/5.4.1:
resolution: {integrity: sha512-9ltS3M2JB0w2EhcYjCdmtrJ+6haZcW6acBolMGIuf01Hql1yrIV01L1aRj7jsaaIULJslEP9Z3vKlEmnJaWJVQ==}
dependencies:
tslib: 2.3.0
zrender: 5.4.1
dev: false
/element-plus/2.2.9_vue@3.2.37:
resolution: {integrity: sha512-jYbL0JkCdv95rkT6trZJjCAizLPySa0qcd2cgq+57SKQnCZAcNDDq4GbTuFRnNavdoeCJnuM3HIficTIUpsMOQ==}
peerDependencies:
@ -3204,6 +3215,10 @@ packages:
engines: {node: '>=0.10.0'}
dev: true
/resize-detector/0.3.0:
resolution: {integrity: sha512-R/tCuvuOHQ8o2boRP6vgx8hXCCy87H1eY9V5imBYeVNyNVpuL9ciReSccLj2gDcax9+2weXy3bc8Vv+NRXeEvQ==}
dev: false
/resolve-from/4.0.0:
resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==}
engines: {node: '>=4'}
@ -3657,6 +3672,10 @@ packages:
resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==}
dev: true
/tslib/2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
dev: false
/tslib/2.4.0:
resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==}
dev: true
@ -3851,6 +3870,23 @@ packages:
vue: 3.2.37
dev: false
/vue-echarts/6.5.1_echarts@5.4.1+vue@3.2.37:
resolution: {integrity: sha512-vlCX65ITq83xkOljip3juL8LyMd4cHOE6Zmp+9u1nPxPrar0irEtTwV80lkFm5yQM4Ef9X9fNdMa6gmsj75xYw==}
requiresBuild: true
peerDependencies:
'@vue/composition-api': ^1.0.5
echarts: ^5.4.1
vue: ^2.6.12 || ^3.1.1
peerDependenciesMeta:
'@vue/composition-api':
optional: true
dependencies:
echarts: 5.4.1
resize-detector: 0.3.0
vue: 3.2.37
vue-demi: 0.13.4_vue@3.2.37
dev: false
/vue-eslint-parser/9.0.3_eslint@8.19.0:
resolution: {integrity: sha512-yL+ZDb+9T0ELG4VIFo/2anAOz8SvBdlqEnQnvJ3M7Scq56DvtjY0VY88bByRZB0D4J0u8olBcfrXTVONXsh4og==}
engines: {node: ^14.17.0 || >=16.0.0}
@ -3980,3 +4016,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'}
dev: true
/zrender/5.4.1:
resolution: {integrity: sha512-M4Z05BHWtajY2241EmMPHglDQAJ1UyHQcYsxDNzD9XLSkPDqMq4bB28v9Pb4mvHnVQ0GxyTklZ/69xCFP6RXBA==}
dependencies:
tslib: 2.3.0
dev: false

@ -0,0 +1,7 @@
<svg viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200">
<path
d="M746.666667 213.333333h-469.333334C243.2 213.333333 213.333333 243.2 213.333333 277.333333v469.333334c0 34.133333 29.866667 64 64 64h469.333334c34.133333 0 64-29.866667 64-64v-469.333334c0-34.133333-29.866667-64-64-64zM256 439.466667h140.8v140.8H256v-140.8z m21.333333 328.533333c-12.8 0-21.333333-8.533333-21.333333-21.333333v-119.466667h140.8V768H277.333333z m307.2 0h-140.8v-140.8h140.8V768z m0-183.466667h-140.8v-140.8h140.8v140.8z m183.466667 162.133334c0 12.8-8.533333 21.333333-21.333333 21.333333h-119.466667v-140.8H768v119.466667z m0-162.133334h-140.8v-140.8H768v140.8z m0-187.733333H256V277.333333c0-12.8 8.533333-21.333333 21.333333-21.333333h469.333334c12.8 0 21.333333 8.533333 21.333333 21.333333v119.466667z"
fill="#1296db"></path>
</svg>

After

Width:  |  Height:  |  Size: 937 B

@ -0,0 +1,10 @@
<svg t="1673874136249" class="icon" viewBox="0 0 1024 1024" version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="200" height="200">
<path
d="M538.4 504.4l280.9 144.3c9.9 5.1 22.2 0.5 26-10 14.3-38.7 22.1-80.6 22.1-124.3 0-186.2-141.6-339.3-323-357.5-7.9-0.8-14.7 5.3-14.7 13.3v320.1c0 5.9 3.4 11.4 8.7 14.1z"
fill="#64B5F6"></path>
<path
d="M492.5 514.5V172.3c0-9.3-8-16.6-17.3-15.8C289 173.4 143.7 332.3 148.7 524.1c5 190.9 161.5 346.1 352.4 349.7 131.3 2.5 246.8-65.5 311.5-168.7 4.6-7.3 2-17-5.7-21L499.8 526.4c-4.5-2.3-7.3-6.9-7.3-11.9z"
fill="#1E88E5"></path>
</svg>

After

Width:  |  Height:  |  Size: 665 B

@ -76,8 +76,7 @@
></component>
<foreignObject
v-else-if="item.type === EDoneJsonType.Vue"
width="100"
height="100"
v-bind="getActualBoundScale(item.actual_bound, item.scale_x, item.scale_y)"
:id="`foreign-object${item.id}`"
>
<component
@ -110,18 +109,7 @@
:id="`rect${item.id}`"
fill="black"
fill-opacity="0"
:x="
item.actual_bound.x -
(item.actual_bound.width / 2) * item.scale_x +
item.actual_bound.width / 2
"
:y="
item.actual_bound.y -
(item.actual_bound.height / 2) * item.scale_y +
item.actual_bound.height / 2
"
:width="item.actual_bound.width * item.scale_x"
:height="item.actual_bound.height * item.scale_y"
v-bind="getActualBoundScale(item.actual_bound, item.scale_x, item.scale_y)"
style="stroke: none; stroke-width: 2; stroke-miterlimit: 10"
:class="`${
globalStore.intention == EGlobalStoreIntention.None ||
@ -666,6 +654,23 @@
const onCanvasContextMenuEvent = (e: MouseEvent) => {
e.preventDefault(); //
};
const getActualBoundScale = (
actual_bound: {
x: number;
y: number;
width: number;
height: number;
},
scale_x: number,
scale_y: number
) => {
return {
x: actual_bound.x - (actual_bound.width / 2) * scale_x + actual_bound.width / 2,
y: actual_bound.y - (actual_bound.height / 2) * scale_y + actual_bound.height / 2,
width: actual_bound.width * scale_x,
height: actual_bound.height * scale_y
};
};
</script>
<style lang="less" scoped>
.canvas {

@ -0,0 +1,71 @@
<!-- eslint-disable vue/html-indent -->
<template>
<el-table v-bind="table_props">
<el-table-column
v-for="item in props.colConfig"
:key="item.prop"
v-bind="item"
></el-table-column>
</el-table>
</template>
<script setup lang="ts">
import { PropType, ref, watchEffect } from 'vue';
import { ElTable, ElTableColumn } from 'element-plus';
const props = defineProps({
colConfig: {
type: Array as PropType<ICol[]>,
default: () => []
},
data: {
type: Array,
default: () => []
},
height: {
type: Number,
default: null
},
maxHeight: {
type: Number,
default: null
},
stripe: {
type: Boolean,
default: false
},
border: {
type: Boolean,
default: false
},
size: {
type: String,
default: ''
},
fit: {
type: Boolean,
default: false
},
operateDisplay: {
type: Boolean,
default: false
},
selectionData: {
type: Array,
default: () => []
}
});
const table_props = ref({});
watchEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { colConfig, ...temp_props } = props;
table_props.value = temp_props;
});
interface ICol {
prop: string;
label: string;
width: string;
fixed: string | boolean;
sortable: boolean;
'show-overflow-tooltip': boolean;
}
</script>
<style scoped lang="scss"></style>

@ -0,0 +1,60 @@
<template>
<v-chart ref="pieChartRef" class="chart" :option="option" autoresize />
</template>
<script lang="ts" setup>
import { use } from 'echarts/core';
import { SVGRenderer } from 'echarts/renderers';
import { PieChart } from 'echarts/charts';
import { TitleComponent, TooltipComponent, LegendComponent } from 'echarts/components';
import VChart, { THEME_KEY } from 'vue-echarts';
import { ref, provide } from 'vue';
use([SVGRenderer, PieChart, TitleComponent, TooltipComponent, LegendComponent]);
provide(THEME_KEY, 'dark');
const option = ref({
title: {
text: 'Traffic Sources',
left: 'center'
},
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b} : {c} ({d}%)'
},
legend: {
orient: 'vertical',
left: 'left',
data: ['Direct', 'Email', 'Ad Networks', 'Video Ads', 'Search Engines']
},
series: [
{
name: 'Traffic Sources',
type: 'pie',
radius: '55%',
center: ['50%', '60%'],
data: [
{ value: 335, name: 'Direct' },
{ value: 310, name: 'Email' },
{ value: 234, name: 'Ad Networks' },
{ value: 135, name: 'Video Ads' },
{ value: 1548, name: 'Search Engines' }
],
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
});
const pieChartRef = ref();
</script>
<style scoped>
.chart {
height: 400px;
}
</style>

@ -56,7 +56,9 @@
'stateless',
'have_animation',
'custom_svg_group',
'element-ui'
'element-ui',
'custom-vue',
'echarts'
]);
const libChange = (val: any) => {
config_center.value = [];

@ -3,6 +3,8 @@ import { IComponentImport, IConfigCenter } from './types';
import customSvgText from '@/components/webtopo-svgedit/components/custom-svg/custom-svg-text/index.vue';
import { vue_config_center } from './vue';
import { ElButton, ElTag } from 'element-plus';
import CommonTable from '@/components/webtopo-svgedit/components/custom-vue/common-table/index.vue';
import PieCharts from '@/components/webtopo-svgedit/components/echarts/pie-charts/index.vue';
export const configCenter: IConfigCenter = {
svg: svgfile_config_center,
vue: vue_config_center
@ -10,5 +12,7 @@ export const configCenter: IConfigCenter = {
export const ComponentImport: IComponentImport = {
'custom-svg-text': customSvgText,
'el-button': ElButton,
'el-tag': ElTag
'el-tag': ElTag,
'custom-vue-common-table': CommonTable,
'pie-charts': PieCharts
};

@ -0,0 +1,115 @@
import { EConfigItemPropsType, EDoneJsonType, IConfigItem } from '@/config-center/types';
export const custom_vue_common_table: IConfigItem = {
name: 'custom-vue-common-table',
title: '通用表格',
tag: 'custom-vue-common-table',
type: EDoneJsonType.Vue,
config: {
can_zoom: true,
have_anchor: true,
actual_rect: true
},
props: {
'col-config': {
title: '列配置',
type: EConfigItemPropsType.JsonEdit,
val: [
{
prop: 'date',
label: '第一列',
width: '120px',
fixed: false,
sortable: false,
'show-overflow-tooltip': false
},
{
prop: 'name',
label: '第二列',
width: '120px',
fixed: false,
sortable: false,
'show-overflow-tooltip': false
},
{
prop: 'address',
label: '第三列测试',
width: '280px',
fixed: false,
sortable: false,
'show-overflow-tooltip': false
}
]
},
data: {
title: '表格数据',
type: EConfigItemPropsType.JsonEdit,
val: [
{
date: '2016-05-03',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-02',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-04',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
},
{
date: '2016-05-01',
name: 'Tom',
address: 'No. 189, Grove St, Los Angeles'
}
]
},
height: {
title: '高度',
type: EConfigItemPropsType.InputNumber,
val: null
},
'max-height': {
title: '最大高度',
type: EConfigItemPropsType.InputNumber,
val: null
},
stripe: {
title: '斑马纹',
type: EConfigItemPropsType.Switch,
val: false
},
border: {
title: '纵向边框',
type: EConfigItemPropsType.Switch,
val: false
},
size: {
title: '尺寸',
type: EConfigItemPropsType.Select,
val: 'default',
options: [
{
label: '大',
value: 'large'
},
{
label: '默认',
value: 'default'
},
{
label: '小',
value: 'small'
}
]
},
fit: {
title: '列宽自撑开',
type: EConfigItemPropsType.Switch,
val: false
}
}
};

@ -0,0 +1,9 @@
import { IConfigComponentGroup } from '@/config-center/types';
import { custom_vue_common_table } from './common-table';
export const custom_vue_group: IConfigComponentGroup = {
groupType: 'custom-vue',
title: '自定义',
list: [custom_vue_common_table]
};

@ -0,0 +1,8 @@
import { IConfigComponentGroup } from '@/config-center/types';
import { pie_charts } from './pie-charts';
export const echarts_group: IConfigComponentGroup = {
groupType: 'echarts',
title: 'echarts图表',
list: [pie_charts]
};

@ -0,0 +1,14 @@
import { EDoneJsonType, IConfigItem } from '../../../types';
export const pie_charts: IConfigItem = {
name: 'pie-charts',
tag: 'pie-charts',
title: '饼图',
type: EDoneJsonType.Vue,
config: {
can_zoom: true,
have_anchor: true,
actual_rect: true
},
props: {}
};

@ -1,4 +1,10 @@
import { IConfigComponentGroup } from '../types';
import { custom_vue_group } from './custom-vue';
import { echarts_group } from './echarts';
import { element_ui_group } from './element-ui';
export const vue_config_center: IConfigComponentGroup[] = Object.seal([element_ui_group]);
export const vue_config_center: IConfigComponentGroup[] = Object.seal([
element_ui_group,
custom_vue_group,
echarts_group
]);

@ -66,7 +66,7 @@ export const useGlobalStore = defineStore('global-store', {
this.create_svg_info = create_svg_info;
},
setDoneJson(done_json: IDoneJson[] | IDoneJson) {
console.log('这里要记录操作历史记录');
console.log('这里要记录操作历史记录', done_json);
if (isOfType(done_json, 'id')) {
this.done_json.push(done_json);
nextTick(() => {

@ -120,7 +120,7 @@ export const objectDeepClone = <T>(object: object, default_val: any = {}) => {
*/
export const setSvgActualInfo = (done_json: IDoneJson) => {
const queryBbox = document.querySelector(`#${done_json.id}`);
// const rectBBox = document.querySelector(`#rect${done_json.id}`);
const rectBBox = document.querySelector(`#rect${done_json.id}`);
if (queryBbox) {
let x = 0,
y = 0,
@ -134,22 +134,46 @@ export const setSvgActualInfo = (done_json: IDoneJson) => {
} else {
(width = (queryBbox as HTMLElement).offsetWidth),
(height = (queryBbox as HTMLElement).offsetHeight);
width = width === 0 ? 100 : width;
height = height === 0 ? 100 : height;
x = 50 - width / 2;
y = 50 - height / 2;
const foreignObjectBox = document.querySelector(`#foreign-object${done_json.id}`);
if (foreignObjectBox) {
if (
foreignObjectBox &&
foreignObjectBox.getAttribute('x') === '0' &&
foreignObjectBox.getAttribute('y') === '0' &&
foreignObjectBox.getAttribute('width') === '0' &&
foreignObjectBox.getAttribute('height') === '0'
) {
foreignObjectBox.setAttribute('x', x.toString());
foreignObjectBox.setAttribute('y', y.toString());
foreignObjectBox.setAttribute('width', width.toString());
foreignObjectBox.setAttribute('height', height.toString());
}
}
// rectBBox.setAttribute('x', x.toString());
// rectBBox.setAttribute('y', y.toString());
// rectBBox.setAttribute('width', width.toString());
// rectBBox.setAttribute('height', height.toString());
done_json.actual_bound = { x, y, width, height };
if (
rectBBox &&
rectBBox.getAttribute('x') === '0' &&
rectBBox.getAttribute('y') === '0' &&
rectBBox.getAttribute('width') === '0' &&
rectBBox.getAttribute('height') === '0'
) {
console.log(rectBBox.getAttribute('x'), 168);
rectBBox.setAttribute('x', x.toString());
rectBBox.setAttribute('y', y.toString());
rectBBox.setAttribute('width', width.toString());
rectBBox.setAttribute('height', height.toString());
}
//实际大小和坐标理论上不会变 但是如果子组件设置了100% 还是会变 所以要做下判断
if (
done_json.actual_bound.x === 0 &&
done_json.actual_bound.y === 0 &&
done_json.actual_bound.width === 0 &&
done_json.actual_bound.height === 0
) {
done_json.actual_bound = { x, y, width, height };
}
done_json.point_coordinate.tl = {
x: done_json.x - (width * done_json.scale_x) / 2,
y: done_json.y - (height * done_json.scale_y) / 2

Loading…
Cancel
Save