usePasteTextClipboardData.ts 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. import { computed } from 'vue'
  2. import { MutationTypes, useStore } from '@/store'
  3. import { decrypt } from '@/utils/crypto'
  4. import { PPTElement, Slide } from '@/types/slides'
  5. import { createRandomCode } from '@/utils/common'
  6. import useHistorySnapshot from '@/hooks/useHistorySnapshot'
  7. import useCreateElement from '@/hooks/useCreateElement'
  8. interface PasteTextClipboardDataOptions {
  9. onlySlide?: boolean;
  10. onlyElements?: boolean;
  11. }
  12. export default () => {
  13. const store = useStore()
  14. const currentSlide = computed<Slide>(() => store.getters.currentSlide)
  15. const { addHistorySnapshot } = useHistorySnapshot()
  16. const { createTextElement } = useCreateElement()
  17. /**
  18. * 粘贴元素(一组)
  19. * @param elements 元素列表数据
  20. */
  21. const pasteElement = (elements: PPTElement[]) => {
  22. const groupIdMap = {}
  23. const elIdMap = {}
  24. for (const element of elements) {
  25. const groupId = element.groupId
  26. if (groupId && !groupIdMap[groupId]) {
  27. groupIdMap[groupId] = createRandomCode()
  28. }
  29. elIdMap[element.id] = createRandomCode()
  30. }
  31. const currentSlideElementIdList = currentSlide.value.elements.map(el => el.id)
  32. for (const element of elements) {
  33. const inCurrentSlide = currentSlideElementIdList.includes(element.id)
  34. element.id = elIdMap[element.id]
  35. if (inCurrentSlide) {
  36. element.left = element.left + 10
  37. element.top = element.top + 10
  38. }
  39. if (element.groupId) element.groupId = groupIdMap[element.groupId]
  40. }
  41. store.commit(MutationTypes.ADD_ELEMENT, elements)
  42. store.commit(MutationTypes.SET_ACTIVE_ELEMENT_ID_LIST, Object.values(elIdMap))
  43. addHistorySnapshot()
  44. }
  45. /**
  46. * 粘贴页面
  47. * @param slide 页面数据
  48. */
  49. const pasteSlide = (slide: Slide) => {
  50. store.commit(MutationTypes.ADD_SLIDE, {
  51. ...slide,
  52. id: createRandomCode(8),
  53. })
  54. addHistorySnapshot()
  55. }
  56. /**
  57. * 粘贴普通文本:创建为新的文本元素
  58. * @param text 文本
  59. */
  60. const pasteText = (text: string) => {
  61. createTextElement({
  62. left: 0,
  63. top: 0,
  64. width: 600,
  65. height: 50,
  66. }, text)
  67. }
  68. /**
  69. * 解析剪贴板内容,根据解析结果选择合适的粘贴方式
  70. * @param text 剪贴板内容
  71. * @param options 配置项:onlySlide -- 仅处理页面粘贴;onlyElements -- 仅处理元素粘贴;
  72. */
  73. const pasteTextClipboardData = (text: string, options?: PasteTextClipboardDataOptions) => {
  74. const onlySlide = options?.onlySlide || false
  75. const onlyElements = options?.onlyElements || false
  76. let clipboardData
  77. try {
  78. clipboardData = JSON.parse(decrypt(text))
  79. }
  80. catch {
  81. clipboardData = text
  82. }
  83. // 元素或页面
  84. if (typeof clipboardData === 'object') {
  85. const { type, data } = clipboardData
  86. if (type === 'elements' && !onlySlide) pasteElement(data)
  87. else if (type === 'slide' && !onlyElements) pasteSlide(data)
  88. }
  89. // 普通文本
  90. else if (!onlyElements && !onlySlide) pasteText(clipboardData)
  91. }
  92. return {
  93. pasteTextClipboardData,
  94. }
  95. }