chartEditStore.ts 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960
  1. import { toRaw } from 'vue'
  2. import { defineStore } from 'pinia'
  3. import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
  4. import { PublicGroupConfigClass } from '@/packages/public/publicConfig'
  5. import debounce from 'lodash/debounce'
  6. import cloneDeep from 'lodash/cloneDeep'
  7. import { defaultTheme, globalThemeJson } from '@/settings/chartThemes/index'
  8. import { requestInterval, previewScaleType, requestIntervalUnit } from '@/settings/designSetting'
  9. // 记录记录
  10. import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
  11. // 全局设置
  12. import { useSettingStore } from '@/store/modules/settingStore/settingStore'
  13. import {
  14. HistoryActionTypeEnum,
  15. HistoryItemType,
  16. HistoryTargetTypeEnum
  17. } from '@/store/modules/chartHistoryStore/chartHistoryStore.d'
  18. import { MenuEnum } from '@/enums/editPageEnum'
  19. import { getUUID, loadingStart, loadingFinish, loadingError, isString, isArray } from '@/utils'
  20. import {
  21. ChartEditStoreEnum,
  22. ChartEditStorage,
  23. ChartEditStoreType,
  24. EditCanvasType,
  25. MousePositionType,
  26. TargetChartType,
  27. RecordChartType,
  28. RequestGlobalConfigType,
  29. EditCanvasConfigType
  30. } from './chartEditStore.d'
  31. const chartHistoryStore = useChartHistoryStore()
  32. const settingStore = useSettingStore()
  33. // 编辑区域内容
  34. export const useChartEditStore = defineStore({
  35. id: 'useChartEditStore',
  36. state: (): ChartEditStoreType => ({
  37. // 画布属性
  38. editCanvas: {
  39. // 编辑区域 Dom
  40. editLayoutDom: null,
  41. editContentDom: null,
  42. // 偏移量
  43. offset: 20,
  44. // 系统控制缩放
  45. scale: 1,
  46. // 用户控制的缩放
  47. userScale: 1,
  48. // 锁定缩放
  49. lockScale: false,
  50. // 初始化
  51. isCreate: false,
  52. // 拖拽中
  53. isDrag: false,
  54. // 框选中
  55. isSelect: false
  56. },
  57. // 右键菜单
  58. rightMenuShow: false,
  59. // 鼠标定位
  60. mousePosition: {
  61. startX: 0,
  62. startY: 0,
  63. x: 0,
  64. y: 0
  65. },
  66. // 目标图表
  67. targetChart: {
  68. hoverId: undefined,
  69. selectId: []
  70. },
  71. // 记录临时数据(复制等)
  72. recordChart: undefined,
  73. // -----------------------
  74. // 画布属性(需存储给后端)
  75. editCanvasConfig: {
  76. // 默认宽度
  77. width: 1920,
  78. // 默认高度
  79. height: 1080,
  80. // 启用滤镜
  81. filterShow: false,
  82. // 色相
  83. hueRotate: 0,
  84. // 饱和度
  85. saturate: 1,
  86. // 对比度
  87. contrast: 1,
  88. // 亮度
  89. brightness: 1,
  90. // 透明度
  91. opacity: 1,
  92. // 变换(暂不更改)
  93. rotateZ: 0,
  94. rotateX: 0,
  95. rotateY: 0,
  96. skewX: 0,
  97. skewY: 0,
  98. // 混合模式
  99. blendMode: 'normal',
  100. // 默认背景色
  101. background: undefined,
  102. backgroundImage: undefined,
  103. // 是否使用纯颜色
  104. selectColor: true,
  105. // chart 主题色
  106. chartThemeColor: defaultTheme || 'dark',
  107. // 全局配置
  108. chartThemeSetting: globalThemeJson,
  109. // 预览方式
  110. previewScaleType: previewScaleType
  111. },
  112. // 数据请求处理(需存储给后端)
  113. requestGlobalConfig: {
  114. requestOriginUrl: '',
  115. requestInterval: requestInterval,
  116. requestIntervalUnit: requestIntervalUnit,
  117. requestParams: {
  118. Body: {
  119. 'form-data': {},
  120. 'x-www-form-urlencoded': {},
  121. json: '',
  122. xml: ''
  123. },
  124. Header: {},
  125. Params: {}
  126. }
  127. },
  128. // 图表数组(需存储给后端)
  129. componentList: []
  130. }),
  131. getters: {
  132. getMousePosition(): MousePositionType {
  133. return this.mousePosition
  134. },
  135. getRightMenuShow(): boolean {
  136. return this.rightMenuShow
  137. },
  138. getEditCanvas(): EditCanvasType {
  139. return this.editCanvas
  140. },
  141. getEditCanvasConfig(): EditCanvasConfigType {
  142. return this.editCanvasConfig
  143. },
  144. getTargetChart(): TargetChartType {
  145. return this.targetChart
  146. },
  147. getRecordChart(): RecordChartType | undefined {
  148. return this.recordChart
  149. },
  150. getRequestGlobalConfig(): RequestGlobalConfigType {
  151. return this.requestGlobalConfig
  152. },
  153. getComponentList(): Array<CreateComponentType | CreateComponentGroupType> {
  154. return this.componentList
  155. },
  156. // 获取需要存储的数据项
  157. getStorageInfo(): ChartEditStorage {
  158. return {
  159. [ChartEditStoreEnum.EDIT_CANVAS_CONFIG]: this.getEditCanvasConfig,
  160. [ChartEditStoreEnum.COMPONENT_LIST]: this.getComponentList,
  161. [ChartEditStoreEnum.REQUEST_GLOBAL_CONFIG]: this.getRequestGlobalConfig
  162. }
  163. }
  164. },
  165. actions: {
  166. // * 设置 editCanvas 数据项
  167. setEditCanvas<T extends keyof EditCanvasType, K extends EditCanvasType[T]>(key: T, value: K) {
  168. this.editCanvas[key] = value
  169. },
  170. // * 设置 editCanvasConfig(需保存后端) 数据项
  171. setEditCanvasConfig<T extends keyof EditCanvasConfigType, K extends EditCanvasConfigType[T]>(key: T, value: K) {
  172. this.editCanvasConfig[key] = value
  173. },
  174. // * 设置右键菜单
  175. setRightMenuShow(value: boolean) {
  176. this.rightMenuShow = value
  177. },
  178. // * 设置目标数据 hover
  179. setTargetHoverChart(hoverId?: TargetChartType['hoverId']) {
  180. this.targetChart.hoverId = hoverId
  181. },
  182. // * 设置目标数据 select
  183. setTargetSelectChart(selectId?: string | string[], push: boolean = false) {
  184. // 重复选中
  185. if (this.targetChart.selectId.find((e: string) => e === selectId)) return
  186. // 无 id 清空
  187. if (!selectId) {
  188. this.targetChart.selectId = []
  189. return
  190. }
  191. // 多选
  192. if (push) {
  193. // 字符串
  194. if (isString(selectId)) {
  195. this.targetChart.selectId.push(selectId)
  196. return
  197. }
  198. // 数组
  199. if (isArray(selectId)) {
  200. this.targetChart.selectId.push(...selectId)
  201. return
  202. }
  203. } else {
  204. // 字符串
  205. if (isString(selectId)) {
  206. this.targetChart.selectId = [selectId]
  207. return
  208. }
  209. // 数组
  210. if (isArray(selectId)) {
  211. this.targetChart.selectId = selectId
  212. return
  213. }
  214. }
  215. },
  216. // * 设置记录数据
  217. setRecordChart(item: RecordChartType | undefined) {
  218. this.recordChart = cloneDeep(item)
  219. },
  220. // * 设置鼠标位置
  221. setMousePosition(x?: number, y?: number, startX?: number, startY?: number): void {
  222. if (x) this.mousePosition.x = x
  223. if (y) this.mousePosition.y = y
  224. if (startX) this.mousePosition.startX = startX
  225. if (startY) this.mousePosition.startY = startY
  226. },
  227. // * 找到目标 id 数据的下标位置,id可为父级或子集数组(无则返回-1)
  228. fetchTargetIndex(id?: string): number {
  229. const targetId = id || (this.getTargetChart.selectId.length && this.getTargetChart.selectId[0]) || undefined
  230. if (!targetId) {
  231. loadingFinish()
  232. return -1
  233. }
  234. const targetIndex = this.componentList.findIndex(e => e.id === targetId)
  235. // 当前
  236. if (targetIndex !== -1) {
  237. return targetIndex
  238. } else {
  239. const length = this.getComponentList.length
  240. for (let i = 0; i < length; i++) {
  241. if (this.getComponentList[i].isGroup) {
  242. for (const cItem of (this.getComponentList[i] as CreateComponentGroupType).groupList) {
  243. if (cItem.id === targetId) {
  244. return i
  245. }
  246. }
  247. }
  248. }
  249. }
  250. return -1
  251. },
  252. // * 统一格式化处理入参 id
  253. idPreFormat(id?: string | string[]) {
  254. const idArr = []
  255. if (!id) {
  256. idArr.push(...this.getTargetChart.selectId)
  257. return idArr
  258. }
  259. if (isString(id)) idArr.push(id)
  260. if (isArray(id)) idArr.push(...id)
  261. return idArr
  262. },
  263. /**
  264. * * 新增组件列表
  265. * @param componentInstance 新图表实例
  266. * @param isHead 是否头部插入
  267. * @param isHistory 是否进行记录
  268. * @returns
  269. */
  270. addComponentList(
  271. componentInstance:
  272. | CreateComponentType
  273. | CreateComponentGroupType
  274. | Array<CreateComponentType | CreateComponentGroupType>,
  275. isHead = false,
  276. isHistory = false
  277. ): void {
  278. if (componentInstance instanceof Array) {
  279. componentInstance.forEach(item => {
  280. this.addComponentList(item, isHead, isHistory)
  281. })
  282. return
  283. }
  284. if (isHistory) {
  285. chartHistoryStore.createAddHistory([componentInstance])
  286. }
  287. if (isHead) {
  288. this.componentList.unshift(componentInstance)
  289. return
  290. }
  291. this.componentList.push(componentInstance)
  292. },
  293. // * 删除组件
  294. removeComponentList(id?: string | string[], isHistory = true): void {
  295. try {
  296. const idArr = this.idPreFormat(id)
  297. const history: Array<CreateComponentType | CreateComponentGroupType> = []
  298. // 遍历所有对象
  299. if (!idArr.length) return
  300. loadingStart()
  301. idArr.forEach(ids => {
  302. const index = this.fetchTargetIndex(ids)
  303. if (index !== -1) {
  304. history.push(this.getComponentList[index])
  305. this.componentList.splice(index, 1)
  306. }
  307. })
  308. isHistory && chartHistoryStore.createDeleteHistory(history)
  309. loadingFinish()
  310. return
  311. } catch (value) {
  312. loadingError()
  313. }
  314. },
  315. // * 重置组件位置
  316. resetComponentPosition(item: CreateComponentType | CreateComponentGroupType, isForward: boolean): void {
  317. const index = this.fetchTargetIndex(item.id)
  318. if (index > -1) {
  319. const componentInstance = this.getComponentList[index]
  320. if (isForward) {
  321. componentInstance.attr = Object.assign(componentInstance.attr, {
  322. x: item.attr.x + item.attr.offsetX,
  323. y: item.attr.y + item.attr.offsetY
  324. })
  325. } else {
  326. componentInstance.attr = Object.assign(componentInstance.attr, {
  327. x: item.attr.x,
  328. y: item.attr.y
  329. })
  330. }
  331. }
  332. },
  333. // * 移动组件
  334. moveComponentList(item: Array<CreateComponentType | CreateComponentGroupType>) {
  335. chartHistoryStore.createMoveHistory(item)
  336. },
  337. // * 更新组件列表某一项的值
  338. updateComponentList(index: number, newData: CreateComponentType | CreateComponentGroupType) {
  339. if (index < 1 && index > this.getComponentList.length) return
  340. this.componentList[index] = newData
  341. },
  342. // * 设置页面样式属性
  343. setPageStyle<T extends keyof CSSStyleDeclaration>(key: T, value: any): void {
  344. const dom = this.getEditCanvas.editContentDom
  345. if (dom) {
  346. dom.style[key] = value
  347. }
  348. },
  349. // * 移动组件列表层级位置到两端
  350. setBothEnds(isEnd = false, isHistory = true): void {
  351. try {
  352. // 暂不支持多选
  353. if (this.getTargetChart.selectId.length > 1) return
  354. loadingStart()
  355. const length = this.getComponentList.length
  356. if (length < 2) {
  357. loadingFinish()
  358. return
  359. }
  360. const index = this.fetchTargetIndex()
  361. const targetData = this.getComponentList[index]
  362. if (index !== -1) {
  363. // 置底排除最底层, 置顶排除最顶层
  364. if ((isEnd && index === 0) || (!isEnd && index === length - 1)) {
  365. loadingFinish()
  366. return
  367. }
  368. // 记录原有位置
  369. const setIndex = (componentInstance: CreateComponentType | CreateComponentGroupType, i: number) => {
  370. const temp = cloneDeep(componentInstance)
  371. temp.attr.zIndex = i
  372. return temp
  373. }
  374. // 历史记录
  375. if (isHistory) {
  376. chartHistoryStore.createLayerHistory(
  377. [setIndex(targetData, index)],
  378. isEnd ? HistoryActionTypeEnum.BOTTOM : HistoryActionTypeEnum.TOP
  379. )
  380. }
  381. // 插入两端
  382. this.addComponentList(targetData, isEnd)
  383. this.getComponentList.splice(isEnd ? index + 1 : index, 1)
  384. loadingFinish()
  385. return
  386. }
  387. } catch (value) {
  388. loadingError()
  389. }
  390. },
  391. // * 置顶
  392. setTop(isHistory = true): void {
  393. this.setBothEnds(false, isHistory)
  394. },
  395. // * 置底
  396. setBottom(isHistory = true): void {
  397. this.setBothEnds(true, isHistory)
  398. },
  399. // * 上移/下移互换图表位置
  400. wrap(isDown = false, isHistory = true) {
  401. try {
  402. // 暂不支持多选
  403. if (this.getTargetChart.selectId.length > 1) return
  404. loadingStart()
  405. const length = this.getComponentList.length
  406. if (length < 2) {
  407. loadingFinish()
  408. return
  409. }
  410. const index: number = this.fetchTargetIndex()
  411. if (index !== -1) {
  412. // 下移排除最底层, 上移排除最顶层
  413. if ((isDown && index === 0) || (!isDown && index === length - 1)) {
  414. loadingFinish()
  415. return
  416. }
  417. // 互换位置
  418. const swapIndex = isDown ? index - 1 : index + 1
  419. const targetItem = this.getComponentList[index]
  420. const swapItem = this.getComponentList[swapIndex]
  421. // 历史记录
  422. if (isHistory) {
  423. chartHistoryStore.createLayerHistory(
  424. [targetItem],
  425. isDown ? HistoryActionTypeEnum.DOWN : HistoryActionTypeEnum.UP
  426. )
  427. }
  428. this.updateComponentList(index, swapItem)
  429. this.updateComponentList(swapIndex, targetItem)
  430. loadingFinish()
  431. return
  432. }
  433. } catch (value) {
  434. loadingError()
  435. }
  436. },
  437. // * 图层上移
  438. setUp(isHistory = true) {
  439. this.wrap(false, isHistory)
  440. },
  441. // * 图层下移
  442. setDown(isHistory = true) {
  443. this.wrap(true, isHistory)
  444. },
  445. // * 复制
  446. setCopy(isCut = false) {
  447. try {
  448. // 暂不支持多选
  449. if (this.getTargetChart.selectId.length > 1) return
  450. // 处理弹窗普通复制的场景
  451. if (document.getElementsByClassName('n-modal-body-wrapper').length) return
  452. loadingStart()
  453. const index: number = this.fetchTargetIndex()
  454. if (index !== -1) {
  455. const copyData: RecordChartType = {
  456. charts: this.getComponentList[index],
  457. type: isCut ? HistoryActionTypeEnum.CUT : HistoryActionTypeEnum.COPY
  458. }
  459. this.setRecordChart(copyData)
  460. window['$message'].success(isCut ? '剪切图表成功' : '复制图表成功!')
  461. loadingFinish()
  462. }
  463. } catch (value) {
  464. loadingError()
  465. }
  466. },
  467. // * 剪切
  468. setCut() {
  469. this.setCopy(true)
  470. },
  471. // * 粘贴
  472. setParse() {
  473. try {
  474. loadingStart()
  475. const recordCharts = this.getRecordChart
  476. if (recordCharts === undefined) {
  477. loadingFinish()
  478. return
  479. }
  480. const parseHandle = (e: CreateComponentType | CreateComponentGroupType) => {
  481. e = cloneDeep(e)
  482. e.attr.x = this.getMousePosition.x + 30
  483. e.attr.y = this.getMousePosition.y + 30
  484. // 外层生成新 id
  485. e.id = getUUID()
  486. // 分组列表生成新 id
  487. if (e.isGroup) {
  488. (e as CreateComponentGroupType).groupList.forEach((item: CreateComponentType) => {
  489. item.id = getUUID()
  490. })
  491. }
  492. return e
  493. }
  494. const isCut = recordCharts.type === HistoryActionTypeEnum.CUT
  495. const targetList = Array.isArray(recordCharts.charts) ? recordCharts.charts : [ recordCharts.charts ]
  496. // 多项
  497. targetList.forEach((e: CreateComponentType | CreateComponentGroupType) => {
  498. this.addComponentList(parseHandle(e), undefined, true)
  499. // 剪切需删除原数据
  500. if (isCut) {
  501. this.setTargetSelectChart(e.id)
  502. this.removeComponentList(undefined, true)
  503. }
  504. })
  505. if (isCut) this.setRecordChart(undefined)
  506. loadingFinish()
  507. } catch (value) {
  508. loadingError()
  509. }
  510. },
  511. // * 撤回/前进 目标处理
  512. setBackAndSetForwardHandle(HistoryItem: HistoryItemType, isForward = false) {
  513. // 处理画布
  514. if (HistoryItem.targetType === HistoryTargetTypeEnum.CANVAS) {
  515. this.editCanvas = HistoryItem.historyData[0] as EditCanvasType
  516. return
  517. }
  518. // 取消选中
  519. this.setTargetSelectChart()
  520. // 重新选中
  521. let historyData = HistoryItem.historyData as Array<CreateComponentType | CreateComponentGroupType>
  522. if (isArray(historyData)) {
  523. // 选中目标元素,支持多个
  524. historyData.forEach((item: CreateComponentType | CreateComponentGroupType) => {
  525. this.setTargetSelectChart(item.id, true)
  526. })
  527. }
  528. // 处理新增类型
  529. const isAdd = HistoryItem.actionType === HistoryActionTypeEnum.ADD
  530. const isDel = HistoryItem.actionType === HistoryActionTypeEnum.DELETE
  531. if (isAdd || isDel) {
  532. if ((isAdd && isForward) || (isDel && !isForward)) {
  533. historyData.forEach(item => {
  534. this.addComponentList(item)
  535. })
  536. return
  537. }
  538. historyData.forEach(item => {
  539. this.removeComponentList(item.id, false)
  540. })
  541. return
  542. }
  543. // 处理移动
  544. const isMove = HistoryItem.actionType === HistoryActionTypeEnum.MOVE
  545. if (isMove) {
  546. historyData.forEach(item => {
  547. this.resetComponentPosition(item, isForward)
  548. })
  549. return
  550. }
  551. // 处理层级
  552. const isTop = HistoryItem.actionType === HistoryActionTypeEnum.TOP
  553. const isBottom = HistoryItem.actionType === HistoryActionTypeEnum.BOTTOM
  554. if (isTop || isBottom) {
  555. if (!isForward) {
  556. // 插入到原有位置
  557. if (isTop) this.getComponentList.pop()
  558. if (isBottom) this.getComponentList.shift()
  559. this.getComponentList.splice(historyData[0].attr.zIndex, 0, historyData[0])
  560. return
  561. }
  562. if (isTop) this.setTop(false)
  563. if (isBottom) this.setBottom(false)
  564. }
  565. const isUp = HistoryItem.actionType === HistoryActionTypeEnum.UP
  566. const isDown = HistoryItem.actionType === HistoryActionTypeEnum.DOWN
  567. if (isUp || isDown) {
  568. if ((isUp && isForward) || (isDown && !isForward)) {
  569. this.setUp(false)
  570. return
  571. }
  572. this.setDown(false)
  573. return
  574. }
  575. // 处理分组
  576. const isGroup = HistoryItem.actionType === HistoryActionTypeEnum.GROUP
  577. const isUnGroup = HistoryItem.actionType === HistoryActionTypeEnum.UN_GROUP
  578. if (isGroup || isUnGroup) {
  579. if ((isGroup && isForward) || (isUnGroup && !isForward)) {
  580. const ids: string[] = []
  581. if (historyData.length > 1) {
  582. historyData.forEach(item => {
  583. ids.push(item.id)
  584. })
  585. } else {
  586. const group = historyData[0] as CreateComponentGroupType
  587. group.groupList.forEach(item => {
  588. ids.push(item.id)
  589. })
  590. }
  591. this.setGroup(ids, false)
  592. return
  593. }
  594. // 都需使用子组件的id去解组
  595. if (historyData.length > 1) {
  596. this.setUnGroup([(historyData[0] as CreateComponentType).id], undefined, false)
  597. } else {
  598. this.setUnGroup([(historyData[0] as CreateComponentGroupType).groupList[0].id], undefined, false)
  599. }
  600. return
  601. }
  602. // 处理锁定
  603. const isLock = HistoryItem.actionType === HistoryActionTypeEnum.LOCK
  604. const isUnLock = HistoryItem.actionType === HistoryActionTypeEnum.UNLOCK
  605. if (isLock || isUnLock) {
  606. if ((isLock && isForward) || (isUnLock && !isForward)) {
  607. historyData.forEach(item => {
  608. this.setLock(!item.status.lock, false)
  609. })
  610. return
  611. }
  612. historyData.forEach(item => {
  613. this.setUnLock(false)
  614. })
  615. return
  616. }
  617. // 处理隐藏
  618. const isHide = HistoryItem.actionType === HistoryActionTypeEnum.HIDE
  619. const isShow = HistoryItem.actionType === HistoryActionTypeEnum.SHOW
  620. if (isHide || isShow) {
  621. if ((isHide && isForward) || (isShow && !isForward)) {
  622. historyData.forEach(item => {
  623. this.setHide(!item.status.hide, false)
  624. })
  625. return
  626. }
  627. historyData.forEach(item => {
  628. this.setShow(false)
  629. })
  630. return
  631. }
  632. },
  633. // * 撤回
  634. setBack() {
  635. try {
  636. loadingStart()
  637. const targetData = chartHistoryStore.backAction()
  638. if (!targetData) {
  639. loadingFinish()
  640. return
  641. }
  642. this.setBackAndSetForwardHandle(targetData)
  643. loadingFinish()
  644. } catch (value) {
  645. loadingError()
  646. }
  647. },
  648. // * 前进
  649. setForward() {
  650. try {
  651. loadingStart()
  652. const targetData = chartHistoryStore.forwardAction()
  653. if (!targetData) {
  654. loadingFinish()
  655. return
  656. }
  657. this.setBackAndSetForwardHandle(targetData, true)
  658. loadingFinish()
  659. } catch (value) {
  660. loadingError()
  661. }
  662. },
  663. // * 移动位置
  664. setMove(keyboardValue: MenuEnum) {
  665. const index = this.fetchTargetIndex()
  666. if (index === -1) return
  667. const attr = this.getComponentList[index].attr
  668. const distance = settingStore.getChartMoveDistance
  669. switch (keyboardValue) {
  670. case MenuEnum.ARROW_UP:
  671. attr.y -= distance
  672. break
  673. case MenuEnum.ARROW_RIGHT:
  674. attr.x += distance
  675. break
  676. case MenuEnum.ARROW_DOWN:
  677. attr.y += distance
  678. break
  679. case MenuEnum.ARROW_LEFT:
  680. attr.x -= distance
  681. break
  682. }
  683. },
  684. // * 创建分组
  685. setGroup(id?: string | string[], isHistory = true) {
  686. try {
  687. const selectIds = this.idPreFormat(id) || this.getTargetChart.selectId
  688. if (selectIds.length < 2) return
  689. loadingStart()
  690. const groupClass = new PublicGroupConfigClass()
  691. // 记录整体坐标
  692. const groupAttr = {
  693. l: this.getEditCanvasConfig.width,
  694. t: this.getEditCanvasConfig.height,
  695. r: 0,
  696. b: 0
  697. }
  698. const targetList: CreateComponentType[] = []
  699. const historyList: CreateComponentType[] = []
  700. // 若目标中有数组则先解组
  701. const newSelectIds: string[] = []
  702. selectIds.forEach((id: string) => {
  703. const targetIndex = this.fetchTargetIndex(id)
  704. if (targetIndex !== -1 && this.getComponentList[targetIndex].isGroup) {
  705. this.setUnGroup(
  706. [id],
  707. (e: CreateComponentType[]) => {
  708. e.forEach(e => {
  709. this.addComponentList(e)
  710. newSelectIds.push(e.id)
  711. })
  712. },
  713. false
  714. )
  715. } else if (targetIndex !== -1) {
  716. newSelectIds.push(id)
  717. }
  718. })
  719. newSelectIds.forEach((id: string) => {
  720. // 获取目标数据并从 list 中移除 (成组后不可再次成组, 断言处理)
  721. const item = this.componentList.splice(this.fetchTargetIndex(id), 1)[0] as CreateComponentType
  722. const { x, y, w, h } = item.attr
  723. const { l, t, r, b } = groupAttr
  724. // 左
  725. groupAttr.l = l > x ? x : l
  726. // 上
  727. groupAttr.t = t > y ? y : t
  728. // 宽
  729. groupAttr.r = r < x + w ? x + w : r
  730. // 高
  731. groupAttr.b = b < y + h ? y + h : b
  732. targetList.push(item)
  733. historyList.push(toRaw(item))
  734. })
  735. // 修改原数据之前,先记录
  736. if (isHistory) chartHistoryStore.createGroupHistory(historyList)
  737. // 设置子组件的位置
  738. targetList.forEach((item: CreateComponentType) => {
  739. item.attr.x = item.attr.x - groupAttr.l
  740. item.attr.y = item.attr.y - groupAttr.t
  741. groupClass.groupList.push(item)
  742. })
  743. // 设置 group 属性
  744. groupClass.attr.x = groupAttr.l
  745. groupClass.attr.y = groupAttr.t
  746. groupClass.attr.w = groupAttr.r - groupAttr.l
  747. groupClass.attr.h = groupAttr.b - groupAttr.t
  748. this.addComponentList(groupClass)
  749. this.setTargetSelectChart(groupClass.id)
  750. loadingFinish()
  751. } catch (error) {
  752. console.log(error)
  753. window['$message'].error('创建分组失败,请联系管理员!')
  754. loadingFinish()
  755. }
  756. },
  757. // * 解除分组
  758. setUnGroup(ids?: string[], callBack?: (e: CreateComponentType[]) => void, isHistory = true) {
  759. try {
  760. const selectGroupIdArr = ids || this.getTargetChart.selectId
  761. if (selectGroupIdArr.length !== 1) return
  762. loadingStart()
  763. // 解组
  764. const unGroup = (targetIndex: number) => {
  765. const targetGroup = this.getComponentList[targetIndex] as CreateComponentGroupType
  766. if (!targetGroup.isGroup) return
  767. // 记录数据
  768. if (isHistory) chartHistoryStore.createUnGroupHistory(cloneDeep([targetGroup]))
  769. // 分离组件并还原位置属性
  770. targetGroup.groupList.forEach(item => {
  771. item.attr.x = item.attr.x + targetGroup.attr.x
  772. item.attr.y = item.attr.y + targetGroup.attr.y
  773. if (!callBack) {
  774. this.addComponentList(item)
  775. }
  776. })
  777. this.setTargetSelectChart(targetGroup.id)
  778. // 删除分组
  779. this.removeComponentList(targetGroup.id, false)
  780. if (callBack) {
  781. callBack(targetGroup.groupList)
  782. }
  783. }
  784. const targetIndex = this.fetchTargetIndex(selectGroupIdArr[0])
  785. // 判断目标是否为分组父级
  786. if (targetIndex !== -1) {
  787. unGroup(targetIndex)
  788. }
  789. loadingFinish()
  790. } catch (error) {
  791. console.log(error)
  792. window['$message'].error('解除分组失败,请联系管理员!')
  793. loadingFinish()
  794. }
  795. },
  796. // * 锁定
  797. setLock(status: boolean = true, isHistory: boolean = true) {
  798. try {
  799. // 暂不支持多选
  800. if (this.getTargetChart.selectId.length > 1) return
  801. loadingStart()
  802. const index: number = this.fetchTargetIndex()
  803. if (index !== -1) {
  804. // 更新状态
  805. const targetItem = this.getComponentList[index]
  806. targetItem.status.lock = status
  807. // 历史记录
  808. if (isHistory) {
  809. status
  810. ? chartHistoryStore.createLockHistory([targetItem])
  811. : chartHistoryStore.createUnLockHistory([targetItem])
  812. }
  813. this.updateComponentList(index, targetItem)
  814. // 锁定添加失焦效果
  815. if (status) this.setTargetSelectChart(undefined)
  816. loadingFinish()
  817. return
  818. }
  819. } catch (value) {
  820. loadingError()
  821. }
  822. },
  823. // * 解除锁定
  824. setUnLock(isHistory: boolean = true) {
  825. this.setLock(false, isHistory)
  826. },
  827. // * 隐藏
  828. setHide(status: boolean = true, isHistory: boolean = true) {
  829. try {
  830. // 暂不支持多选
  831. if (this.getTargetChart.selectId.length > 1) return
  832. loadingStart()
  833. const index: number = this.fetchTargetIndex()
  834. if (index !== -1) {
  835. // 更新状态
  836. const targetItem = this.getComponentList[index]
  837. targetItem.status.hide = status
  838. // 历史记录
  839. if (isHistory) {
  840. status
  841. ? chartHistoryStore.createHideHistory([targetItem])
  842. : chartHistoryStore.createShowHistory([targetItem])
  843. }
  844. this.updateComponentList(index, targetItem)
  845. loadingFinish()
  846. // 隐藏添加失焦效果
  847. if (status) this.setTargetSelectChart(undefined)
  848. }
  849. } catch (value) {
  850. loadingError()
  851. }
  852. },
  853. // * 显示
  854. setShow(isHistory: boolean = true) {
  855. this.setHide(false, isHistory)
  856. },
  857. // ----------------
  858. // * 设置页面大小
  859. setPageSize(scale: number): void {
  860. this.setPageStyle('height', `${this.editCanvasConfig.height * scale}px`)
  861. this.setPageStyle('width', `${this.editCanvasConfig.width * scale}px`)
  862. },
  863. // * 计算缩放
  864. computedScale() {
  865. if (this.getEditCanvas.editLayoutDom) {
  866. // 现有展示区域
  867. const width = this.getEditCanvas.editLayoutDom.clientWidth - this.getEditCanvas.offset * 2 - 5
  868. const height = this.getEditCanvas.editLayoutDom.clientHeight - this.getEditCanvas.offset * 4
  869. // 用户设定大小
  870. const editCanvasWidth = this.editCanvasConfig.width
  871. const editCanvasHeight = this.editCanvasConfig.height
  872. // 需保持的比例
  873. const baseProportion = parseFloat((editCanvasWidth / editCanvasHeight).toFixed(5))
  874. const currentRate = parseFloat((width / height).toFixed(5))
  875. if (currentRate > baseProportion) {
  876. // 表示更宽
  877. const scaleWidth = parseFloat(((height * baseProportion) / editCanvasWidth).toFixed(5))
  878. this.setScale(scaleWidth > 1 ? 1 : scaleWidth)
  879. } else {
  880. // 表示更高
  881. const scaleHeight = parseFloat((width / baseProportion / editCanvasHeight).toFixed(5))
  882. this.setScale(scaleHeight > 1 ? 1 : scaleHeight)
  883. }
  884. } else {
  885. window['$message'].warning('请先创建画布,再进行缩放')
  886. }
  887. },
  888. // * 监听缩放
  889. listenerScale(): Function {
  890. const resize = debounce(this.computedScale, 200)
  891. // 默认执行一次
  892. resize()
  893. // 开始监听
  894. window.addEventListener('resize', resize)
  895. // 销毁函数
  896. const remove = () => {
  897. window.removeEventListener('resize', resize)
  898. }
  899. return remove
  900. },
  901. /**
  902. * * 设置缩放
  903. * @param scale 0~1 number 缩放比例;
  904. * @param force boolean 强制缩放
  905. */
  906. setScale(scale: number, force = false): void {
  907. if (!this.getEditCanvas.lockScale || force) {
  908. this.setPageSize(scale)
  909. this.getEditCanvas.userScale = scale
  910. this.getEditCanvas.scale = scale
  911. }
  912. }
  913. }
  914. })