index.vue 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. <template>
  2. <div class="go-edit">
  3. <n-layout>
  4. <n-layout-header class="go-edit-header go-px-5 go-flex-items-center" bordered>
  5. <div>
  6. <n-text class="go-edit-title go-mr-4">页面在线编辑器</n-text>
  7. <n-button v-if="showOpenFilePicker" class="go-mr-3" size="medium" @click="importJSON">
  8. <template #icon>
  9. <n-icon>
  10. <download-icon></download-icon>
  11. </n-icon>
  12. </template>
  13. 导入
  14. </n-button>
  15. </div>
  16. <n-space>
  17. <n-tag :bordered="false" type="warning"> 「页面失焦保存」 </n-tag>
  18. <n-tag :bordered="false" type="warning"> 「ctrl + s 保存」 </n-tag>
  19. </n-space>
  20. </n-layout-header>
  21. <n-layout-content>
  22. <monaco-editor
  23. v-model:modelValue="content"
  24. language="json"
  25. :editorOptions="{
  26. lineNumbers: 'on',
  27. minimap: { enabled: true }
  28. }"
  29. />
  30. </n-layout-content>
  31. </n-layout>
  32. </div>
  33. </template>
  34. <script setup lang="ts">
  35. import { computed, ref, watch } from 'vue'
  36. import { MonacoEditor } from '@/components/Pages/MonacoEditor'
  37. import { SavePageEnum } from '@/enums/editPageEnum'
  38. import { getSessionStorageInfo } from '../preview/utils'
  39. import type { ChartEditStorageType } from '../preview/index.d'
  40. import { setSessionStorage } from '@/utils'
  41. import { StorageEnum } from '@/enums/storageEnum'
  42. import { icon } from '@/plugins'
  43. const { ChevronBackOutlineIcon, DownloadIcon } = icon.ionicons5
  44. const showOpenFilePicker: Function = (window as any).showOpenFilePicker
  45. let content = ref('')
  46. // 从sessionStorage 获取数据
  47. function getDataBySession() {
  48. const localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as ChartEditStorageType
  49. content.value = JSON.stringify(localStorageInfo, undefined, 2)
  50. }
  51. getDataBySession()
  52. // 返回父窗口
  53. function back() {
  54. opener.name = Date.now()
  55. window.open(opener.location.href, opener.name)
  56. }
  57. // 导入json文本
  58. async function importJSON() {
  59. const files = await showOpenFilePicker()
  60. const file = await files[0].getFile()
  61. const fr = new FileReader()
  62. fr.readAsText(file)
  63. fr.onloadend = () => {
  64. content.value = (fr.result || '').toString()
  65. }
  66. }
  67. // 同步 [画布页失去焦点时同步数据到JSON页,JSON页Ctrl+S 时同步数据到画布页]
  68. opener.addEventListener(SavePageEnum.CHART, (e: any) => {
  69. setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [e.detail])
  70. content.value = JSON.stringify(e.detail, undefined, 2)
  71. })
  72. // 窗口失焦 + 保存 => 同步数据
  73. document.addEventListener('keydown', function (e) {
  74. if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
  75. e.preventDefault()
  76. updateSync()
  77. }
  78. })
  79. addEventListener('blur', updateSync)
  80. // 同步更新
  81. function updateSync() {
  82. if (!opener) {
  83. return window['$message'].error('源窗口已关闭,视图同步失败')
  84. }
  85. try {
  86. const detail = JSON.parse(content.value)
  87. delete detail.id
  88. // 保持id不变
  89. opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
  90. } catch (e) {
  91. window['$message'].error('内容格式有误')
  92. console.log(e)
  93. }
  94. }
  95. </script>
  96. <style lang="scss" scoped>
  97. .go-edit {
  98. display: flex;
  99. flex-direction: column;
  100. height: 100vh;
  101. .go-edit-header {
  102. display: flex;
  103. align-items: center;
  104. height: 60px;
  105. justify-content: space-between;
  106. .go-edit-title {
  107. position: relative;
  108. bottom: 3px;
  109. font-size: 18px;
  110. font-weight: bold;
  111. }
  112. }
  113. @include deep() {
  114. .go-editor-area {
  115. height: calc(100vh - 60px) !important;
  116. }
  117. }
  118. }
  119. </style>