mirror of
https://gitee.com/dromara/go-view.git
synced 2025-10-15 23:06:33 +08:00
feat: 新增事件系统
This commit is contained in:
parent
c2f9f449e8
commit
e33bded469
17
package.json
17
package.json
@ -9,31 +9,32 @@
|
|||||||
"postinstall": "husky install"
|
"postinstall": "husky install"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@vicons/carbon": "^0.12.0",
|
||||||
|
"@vicons/ionicons5": "~0.11.0",
|
||||||
|
"@vueuse/core": "^7.7.1",
|
||||||
"animate.css": "^4.1.1",
|
"animate.css": "^4.1.1",
|
||||||
"axios": "0.23.0",
|
"axios": "0.23.0",
|
||||||
"color": "^4.2.3",
|
"color": "^4.2.3",
|
||||||
"crypto-js": "^4.1.1",
|
"crypto-js": "^4.1.1",
|
||||||
|
"echarts": "^5.3.2",
|
||||||
"echarts-liquidfill": "^3.1.0",
|
"echarts-liquidfill": "^3.1.0",
|
||||||
"highlight.js": "^11.5.0",
|
"highlight.js": "^11.5.0",
|
||||||
"html2canvas": "^1.4.1",
|
"html2canvas": "^1.4.1",
|
||||||
"keymaster": "^1.6.2",
|
"keymaster": "^1.6.2",
|
||||||
|
"lodash": "~4.17.21",
|
||||||
"monaco-editor": "^0.33.0",
|
"monaco-editor": "^0.33.0",
|
||||||
"naive-ui": "2.30.3",
|
"naive-ui": "2.30.3",
|
||||||
"pinia": "^2.0.13",
|
"pinia": "^2.0.13",
|
||||||
"screenfull": "^6.0.1",
|
"screenfull": "^6.0.1",
|
||||||
|
"tiny-emitter": "^2.1.0",
|
||||||
"vue": "^3.2.31",
|
"vue": "^3.2.31",
|
||||||
"vue-demi": "^0.13.1",
|
"vue-demi": "^0.13.1",
|
||||||
|
"vue-echarts": "^6.0.2",
|
||||||
"vue-i18n": "9.1.9",
|
"vue-i18n": "9.1.9",
|
||||||
"vue-router": "4.0.12",
|
"vue-router": "4.0.12",
|
||||||
"vue3-lazyload": "^0.2.5-beta",
|
"vue3-lazyload": "^0.2.5-beta",
|
||||||
"vue3-sketch-ruler": "^1.3.3",
|
"vue3-sketch-ruler": "^1.3.3",
|
||||||
"vuedraggable": "^4.1.0",
|
"vuedraggable": "^4.1.0"
|
||||||
"@vueuse/core": "^7.7.1",
|
|
||||||
"@vicons/carbon": "^0.12.0",
|
|
||||||
"@vicons/ionicons5": "~0.11.0",
|
|
||||||
"echarts": "^5.3.2",
|
|
||||||
"vue-echarts": "^6.0.2",
|
|
||||||
"lodash": "~4.17.21"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/color": "^3.0.3",
|
"@types/color": "^3.0.3",
|
||||||
@ -68,4 +69,4 @@
|
|||||||
"vite-plugin-monaco-editor": "^1.1.0",
|
"vite-plugin-monaco-editor": "^1.1.0",
|
||||||
"vue-tsc": "^0.28.10"
|
"vue-tsc": "^0.28.10"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
38
src/enums/eventEnum.ts
Normal file
38
src/enums/eventEnum.ts
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
export enum EventType {
|
||||||
|
CLICK = 'click',
|
||||||
|
DBCLICK = 'dblclick',
|
||||||
|
CHANGE = 'change',
|
||||||
|
// MOUSE_ENTER = 'mouseenter',
|
||||||
|
// MOUSE_LEAVE = 'mouseleave',
|
||||||
|
MOUNTED = 'vnodeMounted',
|
||||||
|
// OTHER = 'other'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EventTypeTitle = {
|
||||||
|
[EventType.CLICK]: '点击',
|
||||||
|
[EventType.DBCLICK]: '双击',
|
||||||
|
[EventType.CHANGE]: '值变化',
|
||||||
|
// [EventType.MOUSE_ENTER]: '鼠标进入',
|
||||||
|
// [EventType.MOUSE_LEAVE]: '鼠标移开',
|
||||||
|
[EventType.MOUNTED]: '渲染完成',
|
||||||
|
// [EventType.OTHER]: '其它',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum EventTriggerType {
|
||||||
|
COMPONENT = 'component',
|
||||||
|
JAVASCRIPT = 'javascript'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const EventTriggerTypeMap = new Map(
|
||||||
|
[
|
||||||
|
[EventTriggerType.COMPONENT, '组件联动'],
|
||||||
|
[EventTriggerType.JAVASCRIPT, '自定义js'],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
export const CommonEventMap = new Map(
|
||||||
|
[
|
||||||
|
['forceUpdate', '强制更新'],
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
@ -1,4 +1,5 @@
|
|||||||
export * from '@/hooks/useTheme.hook'
|
export * from '@/hooks/useTheme.hook'
|
||||||
export * from '@/hooks/usePreviewScale.hook'
|
export * from '@/hooks/usePreviewScale.hook'
|
||||||
export * from '@/hooks/useCode.hook'
|
export * from '@/hooks/useCode.hook'
|
||||||
export * from '@/hooks/useChartDataFetch.hook'
|
export * from '@/hooks/useChartDataFetch.hook'
|
||||||
|
export * from '@/hooks/useEventBus.hook'
|
67
src/hooks/useEventBus.hook.ts
Normal file
67
src/hooks/useEventBus.hook.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import Emitter from 'tiny-emitter'
|
||||||
|
import { onBeforeUnmount } from 'vue'
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {
|
||||||
|
* on: {
|
||||||
|
* [event]: []
|
||||||
|
* },
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
|
||||||
|
type EventBusListeners = {
|
||||||
|
[key: string]: () => any
|
||||||
|
};
|
||||||
|
|
||||||
|
export type EventBusOptions = {
|
||||||
|
on?: EventBusListeners
|
||||||
|
once?: EventBusListeners
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//@ts-ignore
|
||||||
|
const bus = new Emitter()
|
||||||
|
|
||||||
|
const addListeners = (listeners: EventBusListeners | undefined, isOnce = false): void => {
|
||||||
|
if(!listeners) return
|
||||||
|
Object.keys(listeners).forEach(key => {
|
||||||
|
console.info('监听事件:', key)
|
||||||
|
bus[isOnce ? 'once' : 'on'](key, listeners[key])
|
||||||
|
onBeforeUnmount(() => {
|
||||||
|
bus.off(key, listeners[key])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 转换事件名
|
||||||
|
const convertListeners = (listeners: EventBusListeners, dst: object, prefix = 'prefix'): void => {
|
||||||
|
Object.keys(listeners).forEach((key: string) => {
|
||||||
|
// @ts-ignore
|
||||||
|
dst[`${prefix}:${key}`] = listeners[key]
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export const convertEventBusListeners = (listeners: EventBusOptions, prefix: string): EventBusOptions => {
|
||||||
|
const res = {
|
||||||
|
on: {},
|
||||||
|
once: {},
|
||||||
|
}
|
||||||
|
|
||||||
|
if(listeners.on) {
|
||||||
|
convertListeners(listeners.on, res.on, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
if(listeners.once) {
|
||||||
|
convertListeners(listeners.once, res.once, prefix)
|
||||||
|
}
|
||||||
|
|
||||||
|
return res
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useEventBus = (listeners: EventBusOptions = {}) => {
|
||||||
|
addListeners(listeners.on);
|
||||||
|
addListeners(listeners.once, true)
|
||||||
|
return bus
|
||||||
|
}
|
@ -1,15 +1,14 @@
|
|||||||
import image from '@/assets/images/chart/charts/bar_x.png'
|
import image from '@/assets/images/chart/charts/bar_x.png'
|
||||||
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
|
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
|
||||||
|
import { getComponentConfig } from '@/utils'
|
||||||
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
|
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
|
||||||
|
|
||||||
export const BarCommonConfig: ConfigType = {
|
export const BarCommonConfig: ConfigType = getComponentConfig({
|
||||||
key: 'BarCommon',
|
key: 'BarCommon',
|
||||||
chartKey: 'VBarCommon',
|
|
||||||
conKey: 'VCBarCommon',
|
|
||||||
title: '柱状图',
|
title: '柱状图',
|
||||||
category: ChatCategoryEnum.BAR,
|
category: ChatCategoryEnum.BAR,
|
||||||
categoryName: ChatCategoryEnumName.BAR,
|
categoryName: ChatCategoryEnumName.BAR,
|
||||||
package: PackagesCategoryEnum.CHARTS,
|
package: PackagesCategoryEnum.CHARTS,
|
||||||
chartFrame: ChartFrameEnum.ECHARTS,
|
chartFrame: ChartFrameEnum.ECHARTS,
|
||||||
image
|
image
|
||||||
}
|
})
|
||||||
|
@ -62,7 +62,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType } from 'vue'
|
import { PropType, toRefs } from 'vue'
|
||||||
import { option, WritingModeEnum, WritingModeObject } from './config'
|
import { option, WritingModeEnum, WritingModeObject } from './config'
|
||||||
import {
|
import {
|
||||||
CollapseItem,
|
CollapseItem,
|
||||||
@ -77,6 +77,8 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const { optionData} = toRefs(props)
|
||||||
|
|
||||||
const verticalOptions = [{
|
const verticalOptions = [{
|
||||||
label: WritingModeEnum.HORIZONTAL,
|
label: WritingModeEnum.HORIZONTAL,
|
||||||
value: WritingModeObject[WritingModeEnum.HORIZONTAL]
|
value: WritingModeObject[WritingModeEnum.HORIZONTAL]
|
||||||
|
@ -0,0 +1,16 @@
|
|||||||
|
import { mapToOptions } from '@/utils';
|
||||||
|
|
||||||
|
export enum TextCommonEventEnum {
|
||||||
|
TEST = 'test'
|
||||||
|
}
|
||||||
|
|
||||||
|
export const eventList = mapToOptions(new Map([
|
||||||
|
[TextCommonEventEnum.TEST, '测试内置方法'],
|
||||||
|
]))
|
||||||
|
|
||||||
|
export const TextConfig = {
|
||||||
|
key: 'TextCommon',
|
||||||
|
title: '文字',
|
||||||
|
eventList
|
||||||
|
}
|
||||||
|
|
@ -1,14 +1,15 @@
|
|||||||
|
import { getComponentConfig } from '@/utils';
|
||||||
import image from '@/assets/images/chart/informations/text_static.png'
|
import image from '@/assets/images/chart/informations/text_static.png'
|
||||||
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
|
import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
|
||||||
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
|
import { ChatCategoryEnum,ChatCategoryEnumName } from '../../index.d'
|
||||||
|
import { TextConfig, eventList } from './enum'
|
||||||
|
|
||||||
export const TextCommonConfig: ConfigType = {
|
export const TextCommonConfig: ConfigType = getComponentConfig({
|
||||||
key: 'TextCommon',
|
key: TextConfig.key,
|
||||||
chartKey: 'VTextCommon',
|
title: TextConfig.title,
|
||||||
conKey: 'VCTextCommon',
|
|
||||||
title: '文字',
|
|
||||||
category: ChatCategoryEnum.TEXT,
|
category: ChatCategoryEnum.TEXT,
|
||||||
categoryName: ChatCategoryEnumName.TEXT,
|
categoryName: ChatCategoryEnumName.TEXT,
|
||||||
package: PackagesCategoryEnum.INFORMATIONS,
|
package: PackagesCategoryEnum.INFORMATIONS,
|
||||||
|
eventList,
|
||||||
image
|
image
|
||||||
}
|
})
|
@ -22,9 +22,10 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType, toRefs, shallowReactive, watch } from 'vue'
|
import { PropType, toRefs, shallowReactive, watch } from 'vue'
|
||||||
import { CreateComponentType } from '@/packages/index.d'
|
import { CreateComponentType } from '@/packages/index.d'
|
||||||
import { useChartDataFetch } from '@/hooks'
|
import { useChartDataFetch, useEventBus, convertEventBusListeners } from '@/hooks'
|
||||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||||
import { option as configOption } from './config'
|
import { option as configOption } from './config'
|
||||||
|
import { TextCommonEventEnum } from './enum'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
chartConfig: {
|
chartConfig: {
|
||||||
@ -33,6 +34,16 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const listeners = convertEventBusListeners({
|
||||||
|
on: {
|
||||||
|
[TextCommonEventEnum.TEST]: () => {
|
||||||
|
alert('这是我的内置方法')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, props.chartConfig.id)
|
||||||
|
|
||||||
|
useEventBus(listeners)
|
||||||
|
|
||||||
const { w, h } = toRefs(props.chartConfig.attr)
|
const { w, h } = toRefs(props.chartConfig.attr)
|
||||||
const {
|
const {
|
||||||
dataset,
|
dataset,
|
||||||
|
32
src/packages/index.d.ts
vendored
32
src/packages/index.d.ts
vendored
@ -1,5 +1,7 @@
|
|||||||
import type { GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
import type { GlobalThemeJsonType } from '@/settings/chartThemes/index'
|
||||||
import type { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
import type { RequestConfigType } from '@/store/modules/chartEditStore/chartEditStore.d'
|
||||||
|
import { EventType } from '@/enums/eventEnum';
|
||||||
|
|
||||||
|
|
||||||
export enum ChartFrameEnum {
|
export enum ChartFrameEnum {
|
||||||
// echarts 框架
|
// echarts 框架
|
||||||
@ -12,8 +14,15 @@ export enum ChartFrameEnum {
|
|||||||
STATIC = 'static'
|
STATIC = 'static'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type OptionsType = {
|
||||||
|
label: string
|
||||||
|
value: string
|
||||||
|
[key: string]: string
|
||||||
|
}
|
||||||
|
|
||||||
// 组件配置
|
// 组件配置
|
||||||
export type ConfigType = {
|
export type ConfigType = {
|
||||||
|
id?: string
|
||||||
key: string
|
key: string
|
||||||
chartKey: string
|
chartKey: string
|
||||||
conKey: string
|
conKey: string
|
||||||
@ -22,9 +31,30 @@ export type ConfigType = {
|
|||||||
categoryName: string
|
categoryName: string
|
||||||
package: string
|
package: string
|
||||||
chartFrame?: ChartFrameEnum
|
chartFrame?: ChartFrameEnum
|
||||||
|
eventList?: Array<OptionsType>
|
||||||
image: string | (() => Promise<typeof import('*.png')>)
|
image: string | (() => Promise<typeof import('*.png')>)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
export type EventList = Array<{
|
||||||
|
name: string,
|
||||||
|
event: string,
|
||||||
|
type: string,
|
||||||
|
code: string,
|
||||||
|
uid: string,
|
||||||
|
[key: string]: any
|
||||||
|
}>
|
||||||
|
|
||||||
|
|
||||||
|
export type EventConfigValue = Record<string, {
|
||||||
|
title: string,
|
||||||
|
eventList: EventList
|
||||||
|
}>
|
||||||
|
|
||||||
|
export type EventConfig = {
|
||||||
|
[key: EventType]: EventConfigValue
|
||||||
|
}
|
||||||
|
|
||||||
// 数据请求
|
// 数据请求
|
||||||
interface requestConfig {
|
interface requestConfig {
|
||||||
request: RequestConfigType,
|
request: RequestConfigType,
|
||||||
@ -88,6 +118,8 @@ export interface CreateComponentType extends PublicConfigType {
|
|||||||
key: string
|
key: string
|
||||||
chartConfig: ConfigType
|
chartConfig: ConfigType
|
||||||
option: GlobalThemeJsonType
|
option: GlobalThemeJsonType
|
||||||
|
eventList: Array<OptionsType>
|
||||||
|
eventConfig: EventConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取组件实例类中某个key对应value类型的方法
|
// 获取组件实例类中某个key对应value类型的方法
|
||||||
|
@ -53,6 +53,9 @@ import {
|
|||||||
ArrowForward as ArrowForwardIcon,
|
ArrowForward as ArrowForwardIcon,
|
||||||
Planet as PawIcon,
|
Planet as PawIcon,
|
||||||
Search as SearchIcon,
|
Search as SearchIcon,
|
||||||
|
Reload as ReloadIcon,
|
||||||
|
Add as AddIcon,
|
||||||
|
AddCircle as AddCircleIcon,
|
||||||
} from '@vicons/ionicons5'
|
} from '@vicons/ionicons5'
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@ -82,10 +85,15 @@ import {
|
|||||||
FitToHeight as FitToHeightIcon,
|
FitToHeight as FitToHeightIcon,
|
||||||
FitToWidth as FitToWidthIcon,
|
FitToWidth as FitToWidthIcon,
|
||||||
Filter as FilterIcon,
|
Filter as FilterIcon,
|
||||||
FilterEdit as FilterEditIcon
|
FilterEdit as FilterEditIcon,
|
||||||
|
Edit as EditIcon,
|
||||||
} from '@vicons/carbon'
|
} from '@vicons/carbon'
|
||||||
|
|
||||||
const ionicons5 = {
|
const ionicons5 = {
|
||||||
|
// 新增
|
||||||
|
AddIcon,
|
||||||
|
// 新增2
|
||||||
|
AddCircleIcon,
|
||||||
// 帮助(问号)
|
// 帮助(问号)
|
||||||
HelpOutlineIcon,
|
HelpOutlineIcon,
|
||||||
// 添加
|
// 添加
|
||||||
@ -198,6 +206,7 @@ const ionicons5 = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const carbon = {
|
const carbon = {
|
||||||
|
EditIcon,
|
||||||
// 图表
|
// 图表
|
||||||
RoadmapIcon,
|
RoadmapIcon,
|
||||||
// 信息
|
// 信息
|
||||||
|
@ -126,6 +126,7 @@ export enum ChartEditStoreEnum {
|
|||||||
RECORD_CHART = 'recordChart',
|
RECORD_CHART = 'recordChart',
|
||||||
// 以下需要存储
|
// 以下需要存储
|
||||||
EDIT_CANVAS_CONFIG = 'editCanvasConfig',
|
EDIT_CANVAS_CONFIG = 'editCanvasConfig',
|
||||||
|
EVENT_CONFIG = 'eventConfig',
|
||||||
REQUEST_GLOBAL_CONFIG = 'requestGlobalConfig',
|
REQUEST_GLOBAL_CONFIG = 'requestGlobalConfig',
|
||||||
COMPONENT_LIST = 'componentList',
|
COMPONENT_LIST = 'componentList',
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
RequestGlobalConfigType,
|
RequestGlobalConfigType,
|
||||||
EditCanvasConfigType
|
EditCanvasConfigType
|
||||||
} from './chartEditStore.d'
|
} from './chartEditStore.d'
|
||||||
|
|
||||||
const chartHistoryStore = useChartHistoryStore()
|
const chartHistoryStore = useChartHistoryStore()
|
||||||
const settingStore = useSettingStore()
|
const settingStore = useSettingStore()
|
||||||
|
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { defineAsyncComponent, AsyncComponentLoader } from 'vue'
|
import { defineAsyncComponent, AsyncComponentLoader } from 'vue'
|
||||||
import { AsyncLoading, AsyncSkeletonLoading } from '@/components/GoLoading'
|
import { AsyncLoading, AsyncSkeletonLoading } from '@/components/GoLoading'
|
||||||
|
import { ConfigType } from '@/packages/index.d'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* * 动态注册组件
|
* * 动态注册组件
|
||||||
@ -28,3 +29,12 @@ export const loadSkeletonAsyncComponent = (loader: AsyncComponentLoader<any>) =>
|
|||||||
loadingComponent: AsyncSkeletonLoading,
|
loadingComponent: AsyncSkeletonLoading,
|
||||||
delay: 20,
|
delay: 20,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
export const getComponentConfig = (options: Omit<ConfigType, 'chartKey' | 'conKey' | 'id'>): Partial<ConfigType> => {
|
||||||
|
return {
|
||||||
|
...options,
|
||||||
|
chartKey: `V${options.key}`,
|
||||||
|
conKey: `VC${options.key}`,
|
||||||
|
}
|
||||||
|
}
|
6
src/utils/data.ts
Normal file
6
src/utils/data.ts
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export const mapToOptions = <K extends string = 'key', V extends string = 'value'>(map: Map<string, string>, options = { k: 'label', v: 'value'} as { k: K; v: V }) => Array.from(map, item => {
|
||||||
|
return {
|
||||||
|
[options.k]: item[1],
|
||||||
|
[options.v]: item[0],
|
||||||
|
} as {[key in K | V]: string}
|
||||||
|
});
|
@ -7,3 +7,4 @@ export * from '@/utils/plugin'
|
|||||||
export * from '@/utils/componets'
|
export * from '@/utils/componets'
|
||||||
export * from '@/utils/type'
|
export * from '@/utils/type'
|
||||||
export * from '@/utils/file'
|
export * from '@/utils/file'
|
||||||
|
export * from '@/utils/data'
|
@ -1,13 +1,275 @@
|
|||||||
<template>
|
<template>
|
||||||
<div>
|
<n-collapse :default-expanded-names="Object.values(EventType)">
|
||||||
事件
|
<!-- todo 暂时用any -->
|
||||||
</div>
|
<n-collapse-item
|
||||||
|
v-for="(item, key) in targetData.eventConfig as any"
|
||||||
|
:key="key"
|
||||||
|
:title="item.title"
|
||||||
|
:name="key">
|
||||||
|
<template #header-extra>
|
||||||
|
<n-icon size="24" @click.stop="onAddEvent(item, key)">
|
||||||
|
<component :is="AddCircleIcon"></component>
|
||||||
|
</n-icon>
|
||||||
|
</template>
|
||||||
|
<n-empty
|
||||||
|
v-if="!item.eventList.length"
|
||||||
|
:show-icon="false">
|
||||||
|
</n-empty>
|
||||||
|
<template v-else>
|
||||||
|
<n-data-table
|
||||||
|
:row-key="(rowData:any) => rowData.uid"
|
||||||
|
:columns="columns"
|
||||||
|
:data="item.eventList"
|
||||||
|
/>
|
||||||
|
</template>
|
||||||
|
</n-collapse-item>
|
||||||
|
</n-collapse>
|
||||||
|
|
||||||
|
<n-modal
|
||||||
|
v-model:show="showModal"
|
||||||
|
preset="card"
|
||||||
|
:mask-closable="false"
|
||||||
|
:on-after-leave="onModalClosed">
|
||||||
|
<n-form
|
||||||
|
ref="formRef"
|
||||||
|
label-placement="left"
|
||||||
|
:rules="rules"
|
||||||
|
:model="model"
|
||||||
|
>
|
||||||
|
<n-form-item label="名称" path="name">
|
||||||
|
<n-input v-model:value="model.name" />
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="类型" path="type">
|
||||||
|
<n-select
|
||||||
|
v-model:value="model.type"
|
||||||
|
placeholder="类型"
|
||||||
|
:options="typeOptions"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<template v-if="model.type === EventTriggerType.COMPONENT">
|
||||||
|
<n-form-item label="选择组件" path="componentId">
|
||||||
|
<n-select
|
||||||
|
v-model:value="model.componentId"
|
||||||
|
placeholder="请选择组件"
|
||||||
|
:options="componentListOptions"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
<n-form-item label="触发方法" path="componentMethod">
|
||||||
|
<n-select
|
||||||
|
v-model:value="model.componentMethod"
|
||||||
|
placeholder="请选择触发方法"
|
||||||
|
:options="componentMethodOptions"
|
||||||
|
/>
|
||||||
|
</n-form-item>
|
||||||
|
</template>
|
||||||
|
<template v-else-if="model.type === EventTriggerType.JAVASCRIPT">
|
||||||
|
<n-form-item label="自定义js" path="code">
|
||||||
|
<n-space vertical :style="{width: '100%'}">
|
||||||
|
<n-tag type="info">
|
||||||
|
<span class="func-keyword">function</span> () {
|
||||||
|
</n-tag>
|
||||||
|
<monaco-editor v-model:modelValue="model.code" language="javascript" height="500px"/>
|
||||||
|
<n-tag type="info">}</n-tag>
|
||||||
|
</n-space>
|
||||||
|
</n-form-item>
|
||||||
|
</template>
|
||||||
|
<div style="display: flex; justify-content: center">
|
||||||
|
<n-space>
|
||||||
|
<n-button round type="primary" @click="onSubmit">
|
||||||
|
确认
|
||||||
|
</n-button>
|
||||||
|
<n-button round type="primary" @click="onCancel">
|
||||||
|
取消
|
||||||
|
</n-button>
|
||||||
|
</n-space>
|
||||||
|
</div>
|
||||||
|
</n-form>
|
||||||
|
</n-modal>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
|
import {reactive, ref, h, watch, computed, unref, toRaw, markRaw} from 'vue'
|
||||||
|
import { icon } from '@/plugins/icon'
|
||||||
|
import { MonacoEditor } from '@/components/Pages/MonacoEditor'
|
||||||
|
import { EventType, EventTypeTitle, EventTriggerType, EventTriggerTypeMap, CommonEventMap } from '@/enums/eventEnum'
|
||||||
|
import { FormInst, NSpace as Space, NIcon as Icon } from 'naive-ui'
|
||||||
|
import { getUUID, mapToOptions } from '@/utils'
|
||||||
|
import { useTargetData } from '../hooks/useTargetData.hook'
|
||||||
|
import { CreateComponentType, OptionsType, EventConfig, EventConfigValue } from '@/packages/index.d'
|
||||||
|
|
||||||
|
const { targetData, chartEditStore } = useTargetData();
|
||||||
|
|
||||||
|
// 事件配置
|
||||||
|
const eventConfig = computed<EventConfig>(() => {
|
||||||
|
return targetData.value?.eventConfig
|
||||||
|
})
|
||||||
|
|
||||||
|
// 监听数据变化, 设置初始值
|
||||||
|
watch(targetData, (newVal) => {
|
||||||
|
if(!newVal)return
|
||||||
|
if(!eventConfig.value){
|
||||||
|
newVal.eventConfig = reactive({})
|
||||||
|
}
|
||||||
|
Object.keys(EventTypeTitle).forEach((key: string) => {
|
||||||
|
if(!(key in eventConfig.value)){
|
||||||
|
(newVal.eventConfig as any)[key] = {
|
||||||
|
title: EventTypeTitle[key as EventType],
|
||||||
|
eventList: []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}, {
|
||||||
|
immediate: true
|
||||||
|
})
|
||||||
|
|
||||||
|
const { AddCircleIcon } = icon.ionicons5
|
||||||
|
|
||||||
|
const showModal = ref(false)
|
||||||
|
|
||||||
|
let eventType: EventType = EventType.CLICK
|
||||||
|
let operateCollapse: any = null
|
||||||
|
|
||||||
|
const formRef = ref<FormInst | null>(null)
|
||||||
|
|
||||||
|
const model = ref<Record<string, string>>({
|
||||||
|
uid: '',
|
||||||
|
name: '',
|
||||||
|
type: EventTriggerType.JAVASCRIPT,
|
||||||
|
code: '',
|
||||||
|
componentId: ''
|
||||||
|
});
|
||||||
|
|
||||||
|
const defaultModel: Record<string, string> = {
|
||||||
|
...markRaw(toRaw(unref(model)))
|
||||||
|
}
|
||||||
|
|
||||||
|
const typeOptions = [
|
||||||
|
{label: EventTriggerTypeMap.get(EventTriggerType.COMPONENT), value: EventTriggerType.COMPONENT},
|
||||||
|
{label: EventTriggerTypeMap.get(EventTriggerType.JAVASCRIPT), value: EventTriggerType.JAVASCRIPT},
|
||||||
|
]
|
||||||
|
|
||||||
|
const componentListOptions = computed(() => {
|
||||||
|
return chartEditStore.componentList.map(item => {
|
||||||
|
return {
|
||||||
|
disabled: item.id === targetData.value.id,
|
||||||
|
label: item.chartConfig.title,
|
||||||
|
value: item.id
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
const selectedComponent = computed((): CreateComponentType | void => {
|
||||||
|
return chartEditStore.componentList.find(item => Object.is(item.id, model.value.componentId))
|
||||||
|
})
|
||||||
|
|
||||||
|
const commEventList = mapToOptions(CommonEventMap)
|
||||||
|
|
||||||
|
const componentMethodOptions = computed(() => {
|
||||||
|
return [
|
||||||
|
...commEventList,
|
||||||
|
...(selectedComponent.value ? (selectedComponent.value.chartConfig.eventList as Array<OptionsType>) : [])
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
const rules = {
|
||||||
|
name: { required: true, message: '必填项不能为空' },
|
||||||
|
type: { required: true, message: '必填项不能为空' },
|
||||||
|
componentId: { required: true, message: '必填项不能为空' },
|
||||||
|
componentMethod: { required: true, message: '必填项不能为空' },
|
||||||
|
}
|
||||||
|
|
||||||
|
const onAddEvent = (item: any, type: EventType) => {
|
||||||
|
eventType = type
|
||||||
|
operateCollapse = item
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const onEdit = (rowData: Record<string, any>) => {
|
||||||
|
model.value = {
|
||||||
|
...rowData
|
||||||
|
}
|
||||||
|
eventType = rowData.eventType
|
||||||
|
// @ts-ignore
|
||||||
|
operateCollapse = targetData.value?.eventConfig[eventType]
|
||||||
|
showModal.value = true
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnIconAttr = {
|
||||||
|
size: 18,
|
||||||
|
style: {
|
||||||
|
cursor: 'pointer'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{ title: '名称', key: 'name'},
|
||||||
|
{ title: '类型', key: 'type', render(rowData: any){
|
||||||
|
return EventTriggerTypeMap.get(rowData.type)
|
||||||
|
}},
|
||||||
|
{ title: '操作', render(rowData: any, rowIndex: number){
|
||||||
|
return h(Space, () => (h({
|
||||||
|
render(){
|
||||||
|
return [
|
||||||
|
h(Icon, {
|
||||||
|
...columnIconAttr,
|
||||||
|
title: '编辑',
|
||||||
|
onClick(){
|
||||||
|
onEdit(rowData)
|
||||||
|
}
|
||||||
|
}, () => h(icon.carbon.EditIcon)),
|
||||||
|
h(Icon, {
|
||||||
|
...columnIconAttr,
|
||||||
|
title: '删除',
|
||||||
|
onClick(){
|
||||||
|
((eventConfig.value[rowData.eventType as keyof EventConfig]) as EventConfigValue[string]).eventList.splice(rowIndex, 1)
|
||||||
|
}
|
||||||
|
}, () => h(icon.ionicons5.RemoveIcon))
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})))
|
||||||
|
}},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
const onSubmit = () => {
|
||||||
|
formRef.value?.validate((errors) => {
|
||||||
|
if (!errors && operateCollapse) {
|
||||||
|
if(model.value.uid){
|
||||||
|
const index = operateCollapse.eventList
|
||||||
|
.findIndex((item:any) => item.uid === model.value.uid)
|
||||||
|
if(index > -1){
|
||||||
|
operateCollapse.eventList[index] = {...model.value}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
operateCollapse.eventList.push({
|
||||||
|
...model.value,
|
||||||
|
eventType,
|
||||||
|
uid: getUUID(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
showModal.value = false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const onCancel = () => {
|
||||||
|
showModal.value = false
|
||||||
|
}
|
||||||
|
|
||||||
|
const onModalClosed = () => {
|
||||||
|
Object.keys(model.value).forEach(key => {
|
||||||
|
if(key in defaultModel){
|
||||||
|
model.value[key] = defaultModel[key]
|
||||||
|
}else{
|
||||||
|
model.value[key] = ''
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
.func-keyword {
|
||||||
|
color: #b478cf;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
@ -92,7 +92,8 @@ const {
|
|||||||
ConstructIcon,
|
ConstructIcon,
|
||||||
FlashIcon,
|
FlashIcon,
|
||||||
DesktopOutlineIcon,
|
DesktopOutlineIcon,
|
||||||
LeafIcon
|
LeafIcon,
|
||||||
|
RocketIcon
|
||||||
} = icon.ionicons5
|
} = icon.ionicons5
|
||||||
|
|
||||||
const ContentEdit = loadAsyncComponent(() => import('../ContentEdit/index.vue'))
|
const ContentEdit = loadAsyncComponent(() => import('../ContentEdit/index.vue'))
|
||||||
@ -108,6 +109,9 @@ const ChartData = loadAsyncComponent(() =>
|
|||||||
const ChartAnimation = loadAsyncComponent(() =>
|
const ChartAnimation = loadAsyncComponent(() =>
|
||||||
import('./components/ChartAnimation/index.vue')
|
import('./components/ChartAnimation/index.vue')
|
||||||
)
|
)
|
||||||
|
const ChartEvent = loadAsyncComponent(() =>
|
||||||
|
import('./components/ChartEvent/index.vue')
|
||||||
|
)
|
||||||
|
|
||||||
const collapsed = ref<boolean>(getDetails.value)
|
const collapsed = ref<boolean>(getDetails.value)
|
||||||
|
|
||||||
@ -164,6 +168,12 @@ const canvasTabList = [
|
|||||||
title: '数据',
|
title: '数据',
|
||||||
icon: FlashIcon,
|
icon: FlashIcon,
|
||||||
render: ChartData
|
render: ChartData
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'eventData',
|
||||||
|
title: '事件',
|
||||||
|
icon: RocketIcon,
|
||||||
|
render: ChartEvent
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
</script>
|
</script>
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, toRefs, computed } from 'vue'
|
import { ref, toRefs, computed,isRef } from 'vue'
|
||||||
import { requireErrorImg } from '@/utils'
|
import { requireErrorImg } from '@/utils'
|
||||||
import { useDesignStore } from '@/store/modules/designStore/designStore'
|
import { useDesignStore } from '@/store/modules/designStore/designStore'
|
||||||
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
|
||||||
@ -39,7 +39,10 @@ const props = defineProps({
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
const { image } = toRefs(props.componentData.chartConfig)
|
// 消除页面警告
|
||||||
|
const { image } = isRef(props.componentData.chartConfig) ?
|
||||||
|
toRefs(props.componentData.chartConfig)
|
||||||
|
: props.componentData.chartConfig
|
||||||
|
|
||||||
// 计算当前选中目标
|
// 计算当前选中目标
|
||||||
const select = computed(() => {
|
const select = computed(() => {
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
<template>
|
||||||
|
<component
|
||||||
|
:is="item.chartConfig.chartKey"
|
||||||
|
:chartConfig="item"
|
||||||
|
:themeSetting="themeSetting"
|
||||||
|
:themeColor="themeColor"
|
||||||
|
:style="{...getSizeStyle(item.attr)}"
|
||||||
|
v-on="useEvent ? getEventList(item.eventConfig) : {}"
|
||||||
|
></component>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang='ts' setup>
|
||||||
|
import { PropType, toRefs, getCurrentInstance, ComponentInternalInstance } from 'vue'
|
||||||
|
import { useEventBus } from '@/hooks'
|
||||||
|
import { convertEventBusListeners } from '@/hooks/useEventBus.hook'
|
||||||
|
import { getSizeStyle } from '../../utils'
|
||||||
|
import omit from 'lodash/omit'
|
||||||
|
import { EventTriggerType, EventType } from '@/enums/eventEnum'
|
||||||
|
import { CreateComponentType, EventConfig } from '@/packages/index.d'
|
||||||
|
import { newFunctionHandle } from '@/utils'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
item: {
|
||||||
|
type: Object as PropType<CreateComponentType>,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
themeSetting: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
themeColor: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
useEvent: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
const { item, themeSetting, themeColor, useEvent } = toRefs(props)
|
||||||
|
const instance = getCurrentInstance() as ComponentInternalInstance
|
||||||
|
const bus = useEventBus()
|
||||||
|
/**
|
||||||
|
* @return
|
||||||
|
* {
|
||||||
|
* click: [fn1, fn2],
|
||||||
|
* change: [fn1, fn2],
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
const getEventList = (eventConfig: EventConfig) => {
|
||||||
|
const res = Object.keys(omit(eventConfig, EventType.OTHER)) // 剔除other字段
|
||||||
|
.reduce((previousValue: EventConfig, currentValue: string) => {
|
||||||
|
// @ts-ignore
|
||||||
|
previousValue[currentValue] = eventConfig[currentValue].eventList.map((item: any) => {
|
||||||
|
if(item.type === EventTriggerType.JAVASCRIPT){
|
||||||
|
return (config: CreateComponentType) => {
|
||||||
|
try {
|
||||||
|
newFunctionHandle(config, item.code)
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error, item.code)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
return () => {
|
||||||
|
bus.emit(`${item.componentId}:${item.componentMethod}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return previousValue
|
||||||
|
}, {} as EventConfig)
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
const listeners = {
|
||||||
|
on: {
|
||||||
|
forceUpdate: () => {
|
||||||
|
instance.ctx.$forceUpdate()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
useEventBus(convertEventBusListeners(listeners, item.value.id))
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang='less' scoped>
|
||||||
|
</style>
|
@ -10,13 +10,12 @@
|
|||||||
...getTransformStyle(item.styles)
|
...getTransformStyle(item.styles)
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<component
|
<PreViewRenderItem
|
||||||
:is="item.chartConfig.chartKey"
|
:use-event="true"
|
||||||
:chartConfig="item"
|
:item="item"
|
||||||
:themeSetting="themeSetting"
|
:themeSetting="themeSetting"
|
||||||
:themeColor="themeColor"
|
:themeColor="themeColor">
|
||||||
:style="{...getSizeStyle(item.attr)}"
|
</PreViewRenderItem>
|
||||||
></component>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -26,6 +25,8 @@ import { ChartEditStorageType } from '../../index.d'
|
|||||||
import { chartColors } from '@/settings/chartThemes/index'
|
import { chartColors } from '@/settings/chartThemes/index'
|
||||||
import { animationsClass, getFilterStyle, getTransformStyle } from '@/utils'
|
import { animationsClass, getFilterStyle, getTransformStyle } from '@/utils'
|
||||||
import { getSizeStyle, getComponentAttrStyle } from '../../utils'
|
import { getSizeStyle, getComponentAttrStyle } from '../../utils'
|
||||||
|
import PreViewRenderItem from './PreViewRenderItem.vue'
|
||||||
|
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
localStorageInfo: {
|
localStorageInfo: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user