diff --git a/src/packages/components/Charts/Bars/BarCommon/config.ts b/src/packages/components/Charts/Bars/BarCommon/config.ts index ca8db207..4203a6b9 100644 --- a/src/packages/components/Charts/Bars/BarCommon/config.ts +++ b/src/packages/components/Charts/Bars/BarCommon/config.ts @@ -1,17 +1,12 @@ -import { getUUID } from '@/utils' -import { echartOptionProfixHandle } from '@/packages/utils/chart' +import { echartOptionProfixHandle, publicConfig } from '@/packages/utils' import { BarCommonConfig } from './index' import { ConfigType, CreateComponentType } from '@/packages/index.d' import omit from 'lodash/omit' -export default class Config implements CreateComponentType { - public id = getUUID() +export default class Config extends publicConfig implements CreateComponentType { public key = BarCommonConfig.key - public rename = undefined public chartData: Exclude = omit(BarCommonConfig, ['node']) - public attr = { x: 0, y: 0, w: 500, h: 300 } - // 图表配置项 public option = echartOptionProfixHandle({ tooltip: { @@ -34,10 +29,4 @@ export default class Config implements CreateComponentType { } ] }) - - // 设置坐标 - public setPosition(x: number, y: number): void { - this.attr.x = x - this.attr.y = y - } } \ No newline at end of file diff --git a/src/packages/index.d.ts b/src/packages/index.d.ts index 16fb9695..14c9acdc 100644 --- a/src/packages/index.d.ts +++ b/src/packages/index.d.ts @@ -13,14 +13,16 @@ export type ConfigType = { } // 组件实例类 -export interface CreateComponentType { +export interface PublicConfigType { id: string - key: string rename?: string - attr: { x: number; y: number; w: number; h: number } + attr: { x: number; y: number; w: number; h: number; zIndex: number } + setPosition: Function +} +export interface CreateComponentType extends PublicConfigType { + key: string chartData: ConfigType option: object - setPosition: Function } // 包分类枚举 diff --git a/src/packages/utils/index.ts b/src/packages/utils/index.ts index e852bd1b..d32ad0d3 100644 --- a/src/packages/utils/index.ts +++ b/src/packages/utils/index.ts @@ -1 +1,2 @@ export * from '@/packages/utils/chart' +export * from '@/packages/utils/publicConfig' diff --git a/src/packages/utils/publicConfig.ts b/src/packages/utils/publicConfig.ts new file mode 100644 index 00000000..61965aa5 --- /dev/null +++ b/src/packages/utils/publicConfig.ts @@ -0,0 +1,15 @@ +import { getUUID } from '@/utils' +import { PublicConfigType } from '@/packages/index.d' + +export class publicConfig implements PublicConfigType{ + public id = getUUID() + // 重命名 + public rename = undefined + // 基本信息 + public attr = { x: 0, y: 0, w: 500, h: 300, zIndex: 0 } + // 设置坐标 + public setPosition(x: number, y: number): void { + this.attr.x = x + this.attr.y = y + } +} \ No newline at end of file diff --git a/src/plugins/icon.ts b/src/plugins/icon.ts index 37e7c315..3d9b3c55 100644 --- a/src/plugins/icon.ts +++ b/src/plugins/icon.ts @@ -41,7 +41,8 @@ import { ChevronUp as ChevronUpIcon, ChevronDown as ChevronDownIcon, TimeOutline as TimeOutlineIcon, - ClipboardOutline as ClipboardOutlineIcon + ClipboardOutline as ClipboardOutlineIcon, + Cut as CutIcon } from '@vicons/ionicons5' import { @@ -143,7 +144,9 @@ const ionicons5 = { // 时间 TimeOutlineIcon, // 剪贴板 - ClipboardOutlineIcon + ClipboardOutlineIcon, + // 剪贴 + CutIcon } const carbon = { diff --git a/src/store/modules/chartEditStore/chartEditStore.d.ts b/src/store/modules/chartEditStore/chartEditStore.d.ts index 14158024..afbc2c4d 100644 --- a/src/store/modules/chartEditStore/chartEditStore.d.ts +++ b/src/store/modules/chartEditStore/chartEditStore.d.ts @@ -1,4 +1,5 @@ import { CreateComponentType } from '@/packages/index.d' +import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d' // 编辑画布属性 export enum EditCanvasTypeEnum { @@ -13,6 +14,7 @@ export enum EditCanvasTypeEnum { BACKGROUND = 'background' } +// 编辑区域 export type EditCanvasType = { // 编辑区域 DOM [EditCanvasTypeEnum.EDIT_LAYOUT_DOM]: HTMLElement | null @@ -53,6 +55,12 @@ export type TargetChartType = { selectId?: string } +// 数据记录 +export type RecordChartType = { + charts: CreateComponentType | CreateComponentType[] + type: HistoryActionTypeEnum.CUT | HistoryActionTypeEnum.COPY +} + // Store 枚举 export enum ChartEditStoreEnum { EDIT_RANGE = 'editRange', @@ -60,7 +68,7 @@ export enum ChartEditStoreEnum { RIGHT_MENU_SHOW = 'rightMenuShow', MOUSE_POSITION = 'mousePosition', TARGET_CHART = 'targetChart', - RECORD_CHARTS = 'recordCharts', + RECORD_CHART = 'recordChart', COMPONENT_LIST = 'componentList' } @@ -70,6 +78,6 @@ export interface chartEditStoreType { [ChartEditStoreEnum.RIGHT_MENU_SHOW]: boolean [ChartEditStoreEnum.MOUSE_POSITION]: MousePositionType [ChartEditStoreEnum.TARGET_CHART]: TargetChartType - [ChartEditStoreEnum.RECORD_CHARTS]?: CreateComponentType | CreateComponentType[] + [ChartEditStoreEnum.RECORD_CHART]?: RecordChartType [ChartEditStoreEnum.COMPONENT_LIST]: CreateComponentType[] } diff --git a/src/store/modules/chartEditStore/chartEditStore.ts b/src/store/modules/chartEditStore/chartEditStore.ts index 84109145..e1201eb2 100644 --- a/src/store/modules/chartEditStore/chartEditStore.ts +++ b/src/store/modules/chartEditStore/chartEditStore.ts @@ -7,12 +7,13 @@ import { chartEditStoreType, EditCanvasType, MousePositionType, - TargetChartType + TargetChartType, + RecordChartType } from './chartEditStore.d' // 记录记录 import { useChartHistoryStoreStore } from '@/store/modules/chartHistoryStore/chartHistoryStore' -import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d' +import { HistoryActionTypeEnum, HistoryItemType } from '@/store/modules/chartHistoryStore/chartHistoryStore.d' const chartHistoryStoreStore = useChartHistoryStoreStore() @@ -53,7 +54,7 @@ export const useChartEditStoreStore = defineStore({ selectId: undefined }, // 记录临时数据(复制等) - recordCharts: undefined, + recordChart: undefined, // 图表数组 componentList: [] }), @@ -70,8 +71,8 @@ export const useChartEditStoreStore = defineStore({ getTargetChart():TargetChartType { return this.targetChart }, - getRecordCharts(): CreateComponentType | CreateComponentType[] | undefined { - return this.recordCharts + getRecordChart(): RecordChartType | undefined { + return this.recordChart }, getComponentList(): CreateComponentType[] { return this.componentList @@ -95,14 +96,13 @@ export const useChartEditStoreStore = defineStore({ this.targetChart.selectId = selectId }, // * 设置记录数据 - setRecordCharts(item: CreateComponentType | CreateComponentType[] | undefined) { - this.recordCharts = cloneDeep(item) + setRecordChart(item: RecordChartType | undefined) { + this.recordChart = cloneDeep(item) }, // * 找到目标 id 数据下标位置 fetchTargetIndex(): number { const index = this.componentList.findIndex(e => e.id === this.getTargetChart.selectId) if (index === -1) { - window['$message'].success(`操作失败,无法找到此元素`) loadingError() } return index @@ -202,7 +202,6 @@ export const useChartEditStoreStore = defineStore({ const index:number = this.fetchTargetIndex() if (index !== -1) { - // 下移排除最底层, 上移排除最顶层 if ((isDown && index === 0) || (!isDown && index === length - 1)) { loadingFinish() @@ -233,24 +232,32 @@ export const useChartEditStoreStore = defineStore({ this.wrap(true) }, // * 复制 - setCopy() { + setCopy(isCut = false) { try { loadingStart() const index:number = this.fetchTargetIndex() if (index !== -1) { - this.setRecordCharts(this.getComponentList[index]) - window['$message'].success('复制成功!') + const copyData:RecordChartType = { + charts :this.getComponentList[index], + type: isCut ? HistoryActionTypeEnum.CUT : HistoryActionTypeEnum.COPY + } + this.setRecordChart(copyData) + window['$message'].success(isCut ? '剪切成功' : '复制成功!') loadingFinish() } } catch(value) { loadingError() } }, + // * 剪切 + setCut() { + this.setCopy(true) + }, // * 粘贴 setParse() { try { loadingStart() - const recordCharts = this.getRecordCharts + const recordCharts = this.getRecordChart if (recordCharts === undefined) { loadingFinish() return @@ -264,20 +271,90 @@ export const useChartEditStoreStore = defineStore({ e.attr.y = e.attr.y + 30 return e } - if (Array.isArray(recordCharts)) { - recordCharts.forEach((e: CreateComponentType) => { - console.log(parseHandle(e)); + const isCut = recordCharts.type === HistoryActionTypeEnum.CUT + // 多项 + if (Array.isArray(recordCharts.charts)) { + recordCharts.charts.forEach((e: CreateComponentType) => { this.addComponentList(parseHandle(e), undefined, true) + // 剪切需删除原数据 + if (isCut) { + this.setTargetSelectChart(e.id) + this.removeComponentList() + } }) + if (isCut) this.setRecordChart(undefined) loadingFinish() return } - this.addComponentList(parseHandle(recordCharts), undefined, true) + // 单项 + this.addComponentList(parseHandle(recordCharts.charts), undefined, true) + if(isCut) { + this.setTargetSelectChart(recordCharts.charts.id) + this.removeComponentList() + this.setRecordChart(undefined) + } loadingFinish() } catch(value) { loadingError() } }, + // 撤回处理 + setBackAndSetForwardHandle(item: HistoryItemType, isForward = false) { + // 前进 + if (isForward) { + return + } + console.log(item); + }, + // * 撤回 + setBack() { + try { + loadingStart() + console.log('撤回'); + const targetData = chartHistoryStoreStore.backAction() + if (!targetData) { + loadingFinish() + return + } + if (Array.isArray(targetData)) { + targetData.forEach((e: HistoryItemType) => { + this.setBackAndSetForwardHandle(e) + }) + loadingFinish() + return + } + this.setBackAndSetForwardHandle(targetData) + loadingFinish() + + } catch(value) { + loadingError() + } + }, + // * 前进 + setForward() { + try { + loadingStart() + console.log('前进'); + const targetData = chartHistoryStoreStore.forwardAction() + if (!targetData) { + loadingFinish() + return + } + if (Array.isArray(targetData)) { + targetData.forEach((e: HistoryItemType) => { + this.setBackAndSetForwardHandle(e, true) + }) + loadingFinish() + return + } + this.setBackAndSetForwardHandle(targetData, true) + loadingFinish() + + } catch(value) { + loadingError() + } + }, + // ---------------- // * 设置鼠标位置 setMousePosition(x: number, y: number): void { this.mousePosition.x = x diff --git a/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts b/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts index 78c0d3b5..253e104d 100644 --- a/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts +++ b/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts @@ -11,6 +11,10 @@ export enum HistoryActionTypeEnum { UPDATE = 'update', // 移动 MOVE = 'move', + // 复制 + COPY = 'copy', + // 剪切 + CUT = 'cut', // 粘贴 PASTE = 'paste', // 改变层级 diff --git a/src/store/modules/chartHistoryStore/chartHistoryStore.ts b/src/store/modules/chartHistoryStore/chartHistoryStore.ts index 32e44a0e..6e387ffd 100644 --- a/src/store/modules/chartHistoryStore/chartHistoryStore.ts +++ b/src/store/modules/chartHistoryStore/chartHistoryStore.ts @@ -2,6 +2,7 @@ import { defineStore } from 'pinia' import { CreateComponentType } from '@/packages/index.d' import { ChartLayoutType } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' import { useChartLayoutStore } from '@/store/modules/chartLayoutStore/chartLayoutStore' +import { loadingStart, loadingFinish, loadingError } from '@/utils' import { HistoryStackEnum, HistoryStackItemEnum, @@ -47,9 +48,13 @@ export const useChartHistoryStoreStore = defineStore({ this.createStackItem(canvas, HistoryActionTypeEnum.ADD, HistoryTargetTypeEnum.CANVAS) }, // * 推入记录栈 - pushBackStackItem(item: HistoryItemType | Array): void { + pushBackStackItem(item: HistoryItemType | Array, notClear = false): void { if (item instanceof Array) this.backStack = [...this.backStack, ...item] else this.backStack.push(item) + + // 新动作需清空前进栈 + if(notClear) return + this.clearForwardStack() }, // * 推入前进栈 pushForwardStack(item: HistoryItemType | Array): void { @@ -77,6 +82,51 @@ export const useChartHistoryStoreStore = defineStore({ return this.forwardStack.pop() } }, + // * 清空前进栈 + clearForwardStack() { + this.forwardStack = [] + }, + // * 撤回 + backAction() { + try { + loadingStart() + // 排除画布初始化 + if (this.getBackStack.length > 1) { + const targetData = this.popBackStackItem() + if (!targetData) { + loadingFinish() + return + } + // 移除记录到前进堆 + this.pushForwardStack(targetData) + loadingFinish() + return targetData + } + loadingFinish() + } catch (error) { + loadingError() + } + }, + // * 前进 + forwardAction() { + try { + loadingStart() + if (this.getForwardStack.length) { + const targetData = this.popForwardStack() + if (!targetData) { + loadingFinish() + return + } + // 放入后退栈 + this.pushBackStackItem(targetData, true) + loadingFinish() + return targetData + } + loadingFinish() + } catch (error) { + loadingError() + } + }, // * 新增组件记录 createAddHistory(item: CreateComponentType) { this.createStackItem(item, HistoryActionTypeEnum.ADD, HistoryTargetTypeEnum.CHART) diff --git a/src/views/chart/ContentEdit/hooks/useKeyboard.hook.ts b/src/views/chart/ContentEdit/hooks/useKeyboard.hook.ts index 3803ea13..233b83e2 100644 --- a/src/views/chart/ContentEdit/hooks/useKeyboard.hook.ts +++ b/src/views/chart/ContentEdit/hooks/useKeyboard.hook.ts @@ -1,26 +1,49 @@ import { isMac, addEventListener, removeEventListener } from '@/utils' import { getChartEditStore } from './useStore.hook' +import { MenuEnum } from '@/views/chart/hooks/useContextMenu.hook' const chartEditStore = getChartEditStore() + +export const keyboardValue = { + [MenuEnum.COPY]: 'c', + [MenuEnum.CUT]: 'x', + [MenuEnum.PARSE]: 'v', + [MenuEnum.DELETE]: 'delete', + back: 'z', +} + const KeyboardHandle = (e: KeyboardEvent) => { const ismacRes = isMac() // 暂不支持mac,因为我没有😤👻 - if(ismacRes) return + if (ismacRes) return const key = e.key.toLowerCase() - if (key === 'delete') { + // 删除 + if (key === keyboardValue.delete) { chartEditStore.removeComponentList() return } + // 前进 + if (e.ctrlKey && e.shiftKey && key == keyboardValue.back) { + chartEditStore.setForward() + return + } + if (e.ctrlKey) { switch (key) { // 复制 - case 'c': chartEditStore.setCopy() + case keyboardValue.copy: chartEditStore.setCopy() + break; + // 剪切 + case keyboardValue.cut: chartEditStore.setCut() break; // 粘贴 - case 'v': chartEditStore.setParse() + case keyboardValue.parse: chartEditStore.setParse() + break; + // 撤回 + case keyboardValue.back: chartEditStore.setBack() break; } e.preventDefault() diff --git a/src/views/chart/hooks/useContextMenu.hook.ts b/src/views/chart/hooks/useContextMenu.hook.ts index f69eabf4..4ac70ddb 100644 --- a/src/views/chart/hooks/useContextMenu.hook.ts +++ b/src/views/chart/hooks/useContextMenu.hook.ts @@ -4,14 +4,15 @@ import { CreateComponentType } from '@/packages/index.d' import { renderIcon, loadingError } from '@/utils' import { icon } from '@/plugins' -const { CopyIcon, ClipboardOutlineIcon, TrashIcon, ChevronDownIcon, ChevronUpIcon } = icon.ionicons5 +const { CopyIcon, CutIcon, ClipboardOutlineIcon, TrashIcon, ChevronDownIcon, ChevronUpIcon } = icon.ionicons5 const { UpToTopIcon, DownToBottomIcon } = icon.carbon const chartEditStore = useChartEditStoreStore() -enum MenuEnum { +export enum MenuEnum { DELETE = 'delete', COPY = 'copy', + CUT = 'cut', PARSE = 'parse', TOP = 'top', BOTTOM = 'bottom', @@ -35,6 +36,12 @@ const defaultOptions: MenuOptionsItemType[] = [ icon: renderIcon(CopyIcon), fnHandle: chartEditStore.setCopy }, + { + label: '剪切', + key: MenuEnum.CUT, + icon: renderIcon(CutIcon), + fnHandle: chartEditStore.setCut + }, { label: '粘贴', key: MenuEnum.PARSE,