diff --git a/src/packages/components/Charts/Bars/BarCommon/config.ts b/src/packages/components/Charts/Bars/BarCommon/config.ts index 2bf4feb6..ca8db207 100644 --- a/src/packages/components/Charts/Bars/BarCommon/config.ts +++ b/src/packages/components/Charts/Bars/BarCommon/config.ts @@ -5,9 +5,9 @@ import { ConfigType, CreateComponentType } from '@/packages/index.d' import omit from 'lodash/omit' export default class Config implements CreateComponentType { - public id: string = getUUID() - public key: string = BarCommonConfig.key - + public id = getUUID() + public key = BarCommonConfig.key + public rename = undefined public chartData: Exclude = omit(BarCommonConfig, ['node']) public attr = { x: 0, y: 0, w: 500, h: 300 } diff --git a/src/packages/index.d.ts b/src/packages/index.d.ts index 03f000e3..16fb9695 100644 --- a/src/packages/index.d.ts +++ b/src/packages/index.d.ts @@ -16,6 +16,7 @@ export type ConfigType = { export interface CreateComponentType { id: string key: string + rename?: string attr: { x: number; y: number; w: number; h: number } chartData: ConfigType option: object diff --git a/src/plugins/icon.ts b/src/plugins/icon.ts index 78224474..37e7c315 100644 --- a/src/plugins/icon.ts +++ b/src/plugins/icon.ts @@ -39,7 +39,9 @@ import { Home as HomeIcon, Card as CardIcon, ChevronUp as ChevronUpIcon, - ChevronDown as ChevronDownIcon + ChevronDown as ChevronDownIcon, + TimeOutline as TimeOutlineIcon, + ClipboardOutline as ClipboardOutlineIcon } from '@vicons/ionicons5' import { @@ -53,10 +55,11 @@ import { DicomOverlay as DicomOverlayIcon, UpToTop as UpToTopIcon, DownToBottom as DownToBottomIcon, + StackedMove as StackedMoveIcon } from '@vicons/carbon' const ionicons5 = { - // 帮助 + // 帮助(问号) HelpOutlineIcon, // 添加 DuplicateIcon, @@ -137,6 +140,10 @@ const ionicons5 = { ChevronUpIcon, // 下移 ChevronDownIcon, + // 时间 + TimeOutlineIcon, + // 剪贴板 + ClipboardOutlineIcon } const carbon = { @@ -159,7 +166,9 @@ const carbon = { // 置顶 UpToTopIcon, // 置底 - DownToBottomIcon + DownToBottomIcon, + // 移动 + StackedMoveIcon } // https://www.xicons.org/#/ 还有很多 diff --git a/src/store/modules/chartEditStore/chartEditStore.d.ts b/src/store/modules/chartEditStore/chartEditStore.d.ts index 02b263be..14158024 100644 --- a/src/store/modules/chartEditStore/chartEditStore.d.ts +++ b/src/store/modules/chartEditStore/chartEditStore.d.ts @@ -60,6 +60,7 @@ export enum ChartEditStoreEnum { RIGHT_MENU_SHOW = 'rightMenuShow', MOUSE_POSITION = 'mousePosition', TARGET_CHART = 'targetChart', + RECORD_CHARTS = 'recordCharts', COMPONENT_LIST = 'componentList' } @@ -69,5 +70,6 @@ export interface chartEditStoreType { [ChartEditStoreEnum.RIGHT_MENU_SHOW]: boolean [ChartEditStoreEnum.MOUSE_POSITION]: MousePositionType [ChartEditStoreEnum.TARGET_CHART]: TargetChartType + [ChartEditStoreEnum.RECORD_CHARTS]?: CreateComponentType | CreateComponentType[] [ChartEditStoreEnum.COMPONENT_LIST]: CreateComponentType[] } diff --git a/src/store/modules/chartEditStore/chartEditStore.ts b/src/store/modules/chartEditStore/chartEditStore.ts index e4030c91..84109145 100644 --- a/src/store/modules/chartEditStore/chartEditStore.ts +++ b/src/store/modules/chartEditStore/chartEditStore.ts @@ -1,7 +1,8 @@ import { defineStore } from 'pinia' -import debounce from 'lodash/debounce' -import { loadingStart, loadingFinish, loadingError } from '@/utils' +import { getUUID, loadingStart, loadingFinish, loadingError } from '@/utils' import { CreateComponentType } from '@/packages/index.d' +import debounce from 'lodash/debounce' +import cloneDeep from 'lodash/cloneDeep' import { chartEditStoreType, EditCanvasType, @@ -9,6 +10,12 @@ import { TargetChartType } from './chartEditStore.d' +// 记录记录 +import { useChartHistoryStoreStore } from '@/store/modules/chartHistoryStore/chartHistoryStore' +import { HistoryActionTypeEnum } from '@/store/modules/chartHistoryStore/chartHistoryStore.d' + +const chartHistoryStoreStore = useChartHistoryStoreStore() + // 编辑区域内容 export const useChartEditStoreStore = defineStore({ id: 'useChartEditStoreStore', @@ -24,7 +31,7 @@ export const useChartEditStoreStore = defineStore({ height: 1080, // 偏移量 offset: 20, - // 系统控制缩放 + // 系统控制缩放 scale: 1, // 用户控制的缩放 userScale: 1, @@ -45,6 +52,8 @@ export const useChartEditStoreStore = defineStore({ hoverId: undefined, selectId: undefined }, + // 记录临时数据(复制等) + recordCharts: undefined, // 图表数组 componentList: [] }), @@ -61,6 +70,9 @@ export const useChartEditStoreStore = defineStore({ getTargetChart():TargetChartType { return this.targetChart }, + getRecordCharts(): CreateComponentType | CreateComponentType[] | undefined { + return this.recordCharts + }, getComponentList(): CreateComponentType[] { return this.componentList } @@ -82,6 +94,10 @@ export const useChartEditStoreStore = defineStore({ setTargetSelectChart(selectId?:TargetChartType["selectId"]) { this.targetChart.selectId = selectId }, + // * 设置记录数据 + setRecordCharts(item: CreateComponentType | CreateComponentType[] | undefined) { + this.recordCharts = cloneDeep(item) + }, // * 找到目标 id 数据下标位置 fetchTargetIndex(): number { const index = this.componentList.findIndex(e => e.id === this.getTargetChart.selectId) @@ -91,8 +107,17 @@ export const useChartEditStoreStore = defineStore({ } return index }, - // * 新增组件列表 - addComponentList(chartData: CreateComponentType, isEnd = false): void { + /** + * * 新增组件列表 + * @param chartData 新图表实例 + * @param isEnd 是否末端插入 + * @param isHistory 是否进行记录 + * @returns + */ + addComponentList(chartData: CreateComponentType, isEnd = false, isHistory = false): void { + if(isHistory) { + chartHistoryStoreStore.createAddHistory(chartData) + } if(isEnd) { this.componentList.unshift(chartData) return @@ -105,6 +130,7 @@ export const useChartEditStoreStore = defineStore({ loadingStart() const index = this.fetchTargetIndex() if (index !== -1) { + chartHistoryStoreStore.createDeleteHistory(this.getComponentList[index]) this.componentList.splice(index, 1) loadingFinish() return @@ -118,6 +144,16 @@ export const useChartEditStoreStore = defineStore({ if(index < 1 && index > this.getComponentList.length) return this.componentList[index] = newData }, + // * 设置页面样式属性 + setPageStyle( + key: T, + value: any + ): void { + const dom = this.getEditCanvas.editContentDom + if (dom) { + dom.style[key] = value + } + }, // * 移动组件列表位置到两端 setBothEnds(isEnd = false): void { try { @@ -136,6 +172,7 @@ export const useChartEditStoreStore = defineStore({ return } // 插入两端 + chartHistoryStoreStore.createLaryerHistory(this.getComponentList[index]) this.addComponentList(this.getComponentList[index], isEnd) this.getComponentList.splice(isEnd ? index + 1: index, 1) loadingFinish() @@ -153,16 +190,6 @@ export const useChartEditStoreStore = defineStore({ setBottom(): void { this.setBothEnds(true) }, - // * 设置页面样式属性 - setPageStyle( - key: T, - value: any - ): void { - const dom = this.getEditCanvas.editContentDom - if (dom) { - dom.style[key] = value - } - }, // * 互换图表位置 wrap(isDown = false) { try { @@ -186,8 +213,10 @@ export const useChartEditStoreStore = defineStore({ const targetItem = this.getComponentList[index] const swapItem = this.getComponentList[swapIndex] + chartHistoryStoreStore.createLaryerHistory(targetItem) this.updateComponentList(index, swapItem) this.updateComponentList(swapIndex, targetItem) + loadingFinish() return } @@ -203,6 +232,57 @@ export const useChartEditStoreStore = defineStore({ setDown() { this.wrap(true) }, + // * 复制 + setCopy() { + try { + loadingStart() + const index:number = this.fetchTargetIndex() + if (index !== -1) { + this.setRecordCharts(this.getComponentList[index]) + window['$message'].success('复制成功!') + loadingFinish() + } + } catch(value) { + loadingError() + } + }, + // * 粘贴 + setParse() { + try { + loadingStart() + const recordCharts = this.getRecordCharts + if (recordCharts === undefined) { + loadingFinish() + return + } + const parseHandle = (e: CreateComponentType) => { + e = cloneDeep(e) + // 生成新 id + e.id = getUUID() + // 偏移位置 + e.attr.x = e.attr.x + 30 + e.attr.y = e.attr.y + 30 + return e + } + if (Array.isArray(recordCharts)) { + recordCharts.forEach((e: CreateComponentType) => { + console.log(parseHandle(e)); + this.addComponentList(parseHandle(e), undefined, true) + }) + loadingFinish() + return + } + this.addComponentList(parseHandle(recordCharts), undefined, true) + loadingFinish() + } catch(value) { + loadingError() + } + }, + // * 设置鼠标位置 + setMousePosition(x: number, y: number): void { + this.mousePosition.x = x + this.mousePosition.y = y + }, // * 设置页面变换时候的 Class setPageSizeClass(): void { const dom = this.getEditCanvas.editContentDom @@ -218,11 +298,6 @@ export const useChartEditStoreStore = defineStore({ this.setPageStyle('height', `${this.getEditCanvas.height}px`) this.setPageStyle('width', `${this.getEditCanvas.width}px`) }, - // * 设置鼠标位置 - setMousePosition(x: number, y: number): void { - this.mousePosition.x = x - this.mousePosition.y = y - }, // * 计算缩放 computedScale() { if (this.getEditCanvas.editLayoutDom) { diff --git a/src/store/modules/chartHistoryStore/chartHistoryDefine.ts b/src/store/modules/chartHistoryStore/chartHistoryDefine.ts new file mode 100644 index 00000000..b7ec76d7 --- /dev/null +++ b/src/store/modules/chartHistoryStore/chartHistoryDefine.ts @@ -0,0 +1,16 @@ +import { + HistoryTargetTypeEnum, + HistoryActionTypeEnum +} from './chartHistoryStore.d' + +export const historyActionTypeName = { + [HistoryActionTypeEnum.ADD]: '新增图表', + [HistoryActionTypeEnum.DELETE]: '删除图表', + [HistoryActionTypeEnum.UPDATE]: '修改属性', + [HistoryActionTypeEnum.MOVE]: '移动图表', + [HistoryActionTypeEnum.PASTE]: '粘贴图表', + [HistoryActionTypeEnum.LARYER]: '改变层级', + [HistoryActionTypeEnum.SELECT_HISTORY]: '选择记录', + + [HistoryTargetTypeEnum.CANVAS]: '画布初始化' +} diff --git a/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts b/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts index 6bef1a12..78c0d3b5 100644 --- a/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts +++ b/src/store/modules/chartHistoryStore/chartHistoryStore.d.ts @@ -1,28 +1,56 @@ import { CreateComponentType } from '@/packages/index.d' +import { ChartLayoutType } from '@/store/modules/chartLayoutStore/chartLayoutStore.d' // 操作类型枚举 -export enum HistoryTypeEnum { +export enum HistoryActionTypeEnum { + // 新增 ADD = 'add', + // 删除 DELETE = 'delete', + // 更新(位置,属性) + UPDATE = 'update', + // 移动 MOVE = 'move', + // 粘贴 + PASTE = 'paste', + // 改变层级 + LARYER = 'laryer', + // 选择历史记录 SELECT_HISTORY = 'selectHistory' } +// 对象类型 +export enum HistoryTargetTypeEnum { + CANVAS = 'canvas', + CHART = 'chart' +} + // 历史栈 export enum HistoryStackEnum { - BACK_STACK= 'backStack', - FORWARD_STACK= 'forwardStack', + BACK_STACK = 'backStack', + FORWARD_STACK = 'forwardStack' +} + +// 历史记录项 +export enum HistoryStackItemEnum { + ID = 'id', + TARGET_TYPE = 'targetType', + ACTION_TYPE = 'actionType', + HISTORY_DATA = 'historyData' } // 历史记录项类型 -export interface HistoryItemType extends CreateComponentType { - historyType: HistoryTypeEnum +export interface HistoryItemType { + [HistoryStackItemEnum.ID]: string + [HistoryStackItemEnum.TARGET_TYPE]: HistoryTargetTypeEnum + [HistoryStackItemEnum.ACTION_TYPE]: HistoryActionTypeEnum + [HistoryStackItemEnum.HISTORY_DATA]: CreateComponentType | ChartLayoutType } // 历史 Store 类型 export interface ChartHistoryStoreType { // 后退栈 - [HistoryStackEnum.BACK_STACK]: Array, + [HistoryStackEnum.BACK_STACK]: Array // 前进栈 - [HistoryStackEnum.FORWARD_STACK]: Array, -} \ No newline at end of file + [HistoryStackEnum.FORWARD_STACK]: Array +} diff --git a/src/store/modules/chartHistoryStore/chartHistoryStore.ts b/src/store/modules/chartHistoryStore/chartHistoryStore.ts new file mode 100644 index 00000000..32e44a0e --- /dev/null +++ b/src/store/modules/chartHistoryStore/chartHistoryStore.ts @@ -0,0 +1,105 @@ +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 { + HistoryStackEnum, + HistoryStackItemEnum, + HistoryActionTypeEnum, + HistoryTargetTypeEnum, + HistoryItemType, + ChartHistoryStoreType +} from './chartHistoryStore.d' + +export const useChartHistoryStoreStore = defineStore({ + id: 'useChartHistoryStore', + state: (): ChartHistoryStoreType => ({ + // 后退栈(记录栈) + backStack: [], + // 前进栈 + forwardStack: [] + }), + getters: { + getBackStack(): Array { + return this.backStack + }, + getForwardStack(): Array { + return this.forwardStack + } + }, + actions: { + /** + * * 新增记录并插入栈 + * @param item 图表实例 + * @param actionType 动作类型 + * @param targetType 对象类型(默认图表) + */ + createStackItem(item: CreateComponentType | ChartLayoutType, actionType: HistoryActionTypeEnum, targetType: HistoryTargetTypeEnum = HistoryTargetTypeEnum.CHART) { + this.pushBackStackItem({ + [HistoryStackItemEnum.ID]: new Date().getTime().toString(), + [HistoryStackItemEnum.HISTORY_DATA]: item, + [HistoryStackItemEnum.ACTION_TYPE]: actionType, + [HistoryStackItemEnum.TARGET_TYPE]: targetType, + }) + }, + // * 画布初始化 + canvasInit(canvas: ChartLayoutType) { + this.createStackItem(canvas, HistoryActionTypeEnum.ADD, HistoryTargetTypeEnum.CANVAS) + }, + // * 推入记录栈 + pushBackStackItem(item: HistoryItemType | Array): void { + if (item instanceof Array) this.backStack = [...this.backStack, ...item] + else this.backStack.push(item) + }, + // * 推入前进栈 + pushForwardStack(item: HistoryItemType | Array): void { + if (item instanceof Array) + this.forwardStack = [...this.forwardStack, ...item] + else this.forwardStack.push(item) + }, + // * 移出记录栈 + popBackStackItem( index?: number ): HistoryItemType[] | HistoryItemType | undefined { + const length = this.backStack.length + if (index && length >= index) { + return this.backStack.splice(-index) + } + if (this.backStack.length > 0) { + return this.backStack.pop() + } + }, + // * 移出前进栈 + popForwardStack( index?: number ): HistoryItemType[] | HistoryItemType | undefined { + const length = this.forwardStack.length + if (index && length >= index) { + return this.forwardStack.splice(-index) + } + if (this.forwardStack.length > 0) { + return this.forwardStack.pop() + } + }, + // * 新增组件记录 + createAddHistory(item: CreateComponentType) { + this.createStackItem(item, HistoryActionTypeEnum.ADD, HistoryTargetTypeEnum.CHART) + }, + // * 更新属性记录(大小、图表属性) + createUpdateHistory(item: CreateComponentType) { + this.createStackItem(item, HistoryActionTypeEnum.UPDATE, HistoryTargetTypeEnum.CHART) + }, + // * 删除组件记录 + createDeleteHistory(item: CreateComponentType) { + this.createStackItem(item, HistoryActionTypeEnum.DELETE, HistoryTargetTypeEnum.CHART) + }, + // * 移动组件记录 + createMoveHistory(item: CreateComponentType) { + this.createStackItem(item, HistoryActionTypeEnum.MOVE, HistoryTargetTypeEnum.CHART) + }, + // * 改变层级组件记录 + createLaryerHistory(item: CreateComponentType) { + this.createStackItem(item, HistoryActionTypeEnum.LARYER, HistoryTargetTypeEnum.CHART) + }, + // * 粘贴组件记录 + createPasteHistory(item: CreateComponentType) { + this.createStackItem(item, HistoryActionTypeEnum.PASTE, HistoryTargetTypeEnum.CHART) + }, + } +}) diff --git a/src/store/modules/chartHistoryStore/chartHistoryStore}.ts b/src/store/modules/chartHistoryStore/chartHistoryStore}.ts deleted file mode 100644 index af8ac839..00000000 --- a/src/store/modules/chartHistoryStore/chartHistoryStore}.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { defineStore } from 'pinia' -import { - HistoryStackEnum, - HistoryItemType, - ChartHistoryStoreType -} from './chartHistoryStore.d' -import { setLocalStorage, getLocalStorage } from '@/utils' -import { StorageEnum } from '@/enums/storageEnum' - -export const useChartHistoryStoreStore = defineStore({ - id: 'useChartHistoryStore', - state: (): ChartHistoryStoreType => ({ - // 后退栈(记录栈) - backStack: [], - // 前进栈 - forwardStack: [] - }), - getters: { - getBackStack(): Array { - return this.backStack - }, - getForwardStack(): Array { - return this.forwardStack - } - }, - actions: { - // * 推入记录栈 - addBackStackItem(item: HistoryItemType | Array): void { - if(item instanceof Array) this.backStack = [...this.backStack, ...item] - else this.backStack.push(item) - }, - // * 推入前进栈 - addForwardStack(item: HistoryItemType | Array): void { - if(item instanceof Array) this.forwardStack = [...this.forwardStack, ...item] - else this.forwardStack.push(item) - }, - // * 移出记录栈 - popBackStackItem( - index?: number - ): HistoryItemType[] | HistoryItemType | undefined { - const length = this.backStack.length - if (index && length >= index) { - return this.backStack.splice(-index) - } - if (this.backStack.length > 0) { - return this.backStack.pop() - } - }, - // * 移出前进栈 - popForwardStack( - index?: number - ): HistoryItemType[] | HistoryItemType | undefined { - const length = this.forwardStack.length - if (index && length >= index) { - return this.forwardStack.splice(-index) - } - if (this.forwardStack.length > 0) { - return this.forwardStack.pop() - } - } - } -}) diff --git a/src/store/modules/chartLayoutStore/chartLayoutStore.ts b/src/store/modules/chartLayoutStore/chartLayoutStore.ts index 6e11f8eb..7fffd56b 100644 --- a/src/store/modules/chartLayoutStore/chartLayoutStore.ts +++ b/src/store/modules/chartLayoutStore/chartLayoutStore.ts @@ -8,9 +8,7 @@ const chartEditStore = useChartEditStoreStore() const { GO_CHART_LAYOUT_STORE } = StorageEnum -const storageChartLayout: ChartLayoutType = getLocalStorage( - GO_CHART_LAYOUT_STORE -) +const storageChartLayout: ChartLayoutType = getLocalStorage( GO_CHART_LAYOUT_STORE) // 编辑区域布局和静态设置 export const useChartLayoutStore = defineStore({ diff --git a/src/styles/common/style.scss b/src/styles/common/style.scss index a1fbfc9c..c87a9066 100644 --- a/src/styles/common/style.scss +++ b/src/styles/common/style.scss @@ -18,6 +18,12 @@ text-align: center; } +.go-flex-items-center { + display: flex; + align-items: center; + text-align: center; +} + .go-flex-no-wrap { flex-wrap: nowrap !important; } @@ -108,4 +114,4 @@ .go-px-0 { @extend .go-pl-0; @extend .go-pr-0; -} +} \ No newline at end of file diff --git a/src/utils/page.ts b/src/utils/page.ts index 7c705088..4abdc3e6 100644 --- a/src/utils/page.ts +++ b/src/utils/page.ts @@ -3,7 +3,6 @@ import { ResultEnum } from '@/enums/httpEnum' import { ErrorPageNameMap, PageEnum } from '@/enums/pageEnum' import router from '@/router' import { docPath, giteeSourceCodePath } from '@/settings/pathConst' -import { goDialog } from '@/utils/plugin' /** * * 根据名字跳转路由 @@ -139,6 +138,6 @@ export const fetchRouteParams = () => { * * 回到主页面 * @param confirm */ -export const goHome = (confirm: boolean, params: T) => { +export const goHome = () => { routerTurnByName(PageEnum.BASE_HOME_NAME) } diff --git a/src/utils/utils.ts b/src/utils/utils.ts index 014b155b..0f126148 100644 --- a/src/utils/utils.ts +++ b/src/utils/utils.ts @@ -1,7 +1,7 @@ import { h } from 'vue' import { NIcon } from 'naive-ui' import screenfull from 'screenfull' -import debounce from 'lodash/debounce' +import throttle from 'lodash/throttle' /** * * 生成一个不重复的ID @@ -91,12 +91,18 @@ export const setDomAttribute = { + return /macintosh|mac os x/i.test(navigator.userAgent) +} /** * * 挂载监听 */ -export const goAddEventListener = ( - target: EventTarget, +export const addEventListener = ( + target: HTMLElement | Document, type: K, listener: any, options?: boolean | AddEventListenerOptions | undefined @@ -104,7 +110,7 @@ export const goAddEventListener = ( if (!target) return target.addEventListener( type, - debounce(listener, 300, { + throttle(listener, 300, { leading: true, trailing: false }), @@ -115,10 +121,10 @@ export const goAddEventListener = ( /** * * 卸载监听 */ -export const goRemoveEventListener = ( - target: EventTarget, +export const removeEventListener = ( + target: HTMLElement | Document, type: K, - listener: EventListenerOrEventListenerObject + listener: any ) => { if (!target) return target.removeEventListener(type, listener) diff --git a/src/views/chart/ContentEdit/components/EditBottom/index.vue b/src/views/chart/ContentEdit/components/EditBottom/index.vue index 768ab559..feadd874 100644 --- a/src/views/chart/ContentEdit/components/EditBottom/index.vue +++ b/src/views/chart/ContentEdit/components/EditBottom/index.vue @@ -1,19 +1,17 @@