Sfoglia il codice sorgente

feat: 预览页\JSON编辑页\图表页保存同步更新

潘潘 3 anni fa
parent
commit
5dc58362cc

+ 8 - 0
src/enums/editPageEnum.ts

@@ -9,6 +9,12 @@ export enum DragKeyEnum {
   DRAG_KEY = 'ChartData'
 }
 
+// 不同页面保存操作
+export enum SavePageEnum {
+  CHART = 'SaveChart',
+  JSON = 'SaveJSON'
+}
+
 // 操作枚举
 export enum MenuEnum {
   // 移动
@@ -42,6 +48,8 @@ export enum MenuEnum {
   BACK = 'back',
   // 前进
   FORWORD = 'forward',
+  // 保存
+  SAVE = 'save',
   // 锁定
   LOCK = 'lock',
   // 解除锁定

+ 6 - 0
src/enums/pageEnum.ts

@@ -12,6 +12,12 @@ export enum PreviewEnum {
   CHART_PREVIEW_NAME = 'ChartPreview',
 }
 
+export enum EditEnum {
+  //  图表JSON编辑
+  CHART_EDIT = '/chart/edit/:id(.*)*',
+  CHART_EDIT_NAME = 'ChartEdit',
+}
+
 export enum PageEnum {
   // 登录
   BASE_LOGIN = '/login',

+ 2 - 1
src/router/index.ts

@@ -21,7 +21,8 @@ const RootRoute: Array<RouteRecordRaw> = [
       ...HttpErrorPage,
       modules.projectRoutes,
       modules.chartRoutes,
-      modules.previewRoutes
+      modules.previewRoutes,
+      modules.editRoutes
     ]
   }
 ]

+ 20 - 0
src/router/modules/edit.route.ts

@@ -0,0 +1,20 @@
+import { RouteRecordRaw } from 'vue-router'
+import { EditEnum } from '@/enums/pageEnum'
+
+// 引入路径
+const importPath = {
+  [EditEnum.CHART_EDIT_NAME]: () => import('@/views/edit/index.vue')
+}
+
+const chartRoutes: RouteRecordRaw = {
+  path: EditEnum.CHART_EDIT,
+  name: EditEnum.CHART_EDIT_NAME,
+  component: importPath[EditEnum.CHART_EDIT_NAME],
+  meta: {
+    title: '编辑',
+    isRoot: true
+  }
+}
+
+
+export default chartRoutes

+ 3 - 1
src/router/modules/index.ts

@@ -1,9 +1,11 @@
 import projectRoutes from './project.router'
 import chartRoutes from './chart.route'
 import previewRoutes from './preview.route'
+import editRoutes from './edit.route'
 
 export default {
   projectRoutes,
   chartRoutes,
-  previewRoutes
+  previewRoutes,
+  editRoutes
 }

+ 1 - 1
src/router/modules/preview.route.ts

@@ -3,7 +3,7 @@ import { PreviewEnum } from '@/enums/pageEnum'
 
 // 引入路径
 const importPath = {
-  'PreviewEnum.CHART_PREVIEW_NAME': () => import('@/views/preview/index.vue')
+  'PreviewEnum.CHART_PREVIEW_NAME': () => import('@/views/preview/wrapper.vue')
 }
 
 const chartRoutes: RouteRecordRaw = {

+ 57 - 2
src/views/chart/ContentEdit/components/EditTools/index.vue

@@ -58,17 +58,65 @@
 </template>
 
 <script setup lang="ts">
-import { ref, computed, h } from 'vue'
+import { ref, computed, h, onBeforeUnmount } from 'vue'
 import { useSettingStore } from '@/store/modules/settingStore/settingStore'
 import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
+import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
+import { fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
+import { EditEnum } from '@/enums/pageEnum'
+import { StorageEnum } from '@/enums/storageEnum'
+import { useRoute } from 'vue-router'
+import { useSync } from '@/views/chart/hooks/useSync.hook'
+import { SavePageEnum } from '@/enums/editPageEnum'
 import { GoSystemSet } from '@/components/GoSystemSet/index'
 import { exportHandle } from './utils'
 import { useFile } from './hooks/useFile.hooks'
 import { BtnListType, TypeEnum } from './index.d'
 import { icon } from '@/plugins'
 
-const { DownloadIcon, ShareIcon, PawIcon, SettingsSharpIcon } = icon.ionicons5
+const { DownloadIcon, ShareIcon, PawIcon, SettingsSharpIcon, CodeSlashIcon } = icon.ionicons5
 const settingStore = useSettingStore()
+const chartEditStore = useChartEditStore()
+const routerParamsInfo = useRoute()
+const { updateComponent } = useSync()
+
+// 编辑
+const editHandle = () => {
+  // 获取id路径
+  const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href')
+  if (!path) return
+  let { id } = routerParamsInfo.params as any
+  id = typeof id === 'string' ? id : id[0]
+  updateToSession(id)
+  routerTurnByPath(path, [id], undefined, true)
+}
+
+// 把内存中的数据同步到SessionStorage 便于传递给新窗口初始化数据
+function updateToSession(id: string) {
+  const storageInfo = chartEditStore.getStorageInfo
+  const sessionStorageInfo = getLocalStorage(StorageEnum.GO_CHART_STORAGE_LIST) || []
+
+  if (sessionStorageInfo?.length) {
+    const repeateIndex = sessionStorageInfo.findIndex((e: { id: string }) => e.id === id)
+    // 重复替换
+    if (repeateIndex !== -1) {
+      sessionStorageInfo.splice(repeateIndex, 1, { ...storageInfo, id })
+      setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
+    } else {
+      sessionStorageInfo.push({ ...storageInfo, id})
+      setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
+    }
+  } else {
+    setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...storageInfo, id }])
+  }
+}
+
+onBeforeUnmount((() => {
+  // 【监听JSON代码 刷新图表】
+  const updateFn = (e: any) => updateComponent(e!.detail, true, false)
+  addEventListener(SavePageEnum.JSON, updateFn)
+  return () => removeEventListener(SavePageEnum.JSON, updateFn)
+})())
 
 // 鼠标悬停定时器
 let mouseTime: any = null
@@ -95,6 +143,13 @@ const btnList: BtnListType[] = [
     name: '导入',
     icon: DownloadIcon
   },
+  {
+    key: 'edit',
+    type: TypeEnum.BUTTON,
+    name: '编辑JSON',
+    icon: CodeSlashIcon,
+    handle: editHandle
+  },
   {
     key: 'setting',
     type: TypeEnum.BUTTON,

+ 10 - 1
src/views/chart/hooks/useKeyboard.hook.ts

@@ -1,5 +1,5 @@
 import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
-import { WinKeyboard, MacKeyboard, MenuEnum } from '@/enums/editPageEnum'
+import { WinKeyboard, MacKeyboard, MenuEnum, SavePageEnum } from '@/enums/editPageEnum'
 import throttle from 'lodash/throttle'
 import debounce from 'lodash/debounce'
 import keymaster from 'keymaster'
@@ -23,6 +23,7 @@ export const winKeyboardValue = {
   [MenuEnum.DELETE]: 'delete',
   [MenuEnum.BACK]: winCtrlMerge('z'),
   [MenuEnum.FORWORD]: winCtrlMerge(winShiftMerge('z')),
+  [MenuEnum.SAVE]: winCtrlMerge('s'),
   [MenuEnum.GROUP]: winCtrlMerge('g'),
   [MenuEnum.UN_GROUP]: winCtrlMerge(winShiftMerge('g')),
   [MenuEnum.LOCK]: winCtrlMerge('l'),
@@ -48,6 +49,7 @@ export const macKeyboardValue = {
   [MenuEnum.DELETE]: macCtrlMerge('backspace'),
   [MenuEnum.BACK]: macCtrlMerge('z'),
   [MenuEnum.FORWORD]: macCtrlMerge(macShiftMerge('z')),
+  [MenuEnum.SAVE]: macCtrlMerge('s'),
   [MenuEnum.GROUP]: macCtrlMerge('g'),
   [MenuEnum.UN_GROUP]: macCtrlMerge(macShiftMerge('g')),
   [MenuEnum.LOCK]: macCtrlMerge('l'),
@@ -71,6 +73,7 @@ const winKeyList: Array<string> = [
   winKeyboardValue.back,
   winKeyboardValue.forward,
 
+  winKeyboardValue.save,
   winKeyboardValue.group,
   winKeyboardValue.unGroup,
 
@@ -96,6 +99,7 @@ const macKeyList: Array<string> = [
   macKeyboardValue.back,
   macKeyboardValue.forward,
 
+  macKeyboardValue.save,
   macKeyboardValue.group,
   macKeyboardValue.unGroup,
 
@@ -203,6 +207,11 @@ export const useAddKeyboard = () => {
       case keyboardValue.show:
         keymaster(e, throttle(() => { chartEditStore.setShow(); return false }, throttleTime))
         break;
+
+      // 保存 ct+s
+      case keyboardValue.save:
+        keymaster(e, throttle(() => { dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo })); return false }, 200))
+        break;
     }
   }
   winKeyList.forEach((key: string) => {

+ 99 - 0
src/views/edit/index.vue

@@ -0,0 +1,99 @@
+<template>
+  <div class="go-edit">
+    <n-layout has-sider sider-placement="right">
+      <n-layout-content>
+        <div>
+          <n-space class="go-mx-1 go-my-1">
+            <n-button size="medium" @click="back">返回</n-button>
+            <n-button v-if="showOpenFilePicker" size="medium" @click="importJSON">导入</n-button>
+            <!-- <n-button size="medium" type="primary" @click="confirm">覆盖</n-button> -->
+          </n-space>
+        </div>
+        <monaco-editor
+          v-model:modelValue="content"
+          language="json"
+          :editorOptions="{
+            lineNumbers: 'on',
+            minimap: { enabled: true }
+          }"
+        />
+      </n-layout-content>
+    </n-layout>
+  </div>
+</template>
+
+<script setup lang="ts">
+import { computed, ref, watch } from 'vue'
+import { MonacoEditor } from '@/components/Pages/MonacoEditor'
+import { SavePageEnum } from '@/enums/editPageEnum'
+import { getSessionStorageInfo } from '../preview/utils'
+import type { ChartEditStorageType } from '../preview/index.d'
+import { setSessionStorage } from '@/utils'
+import { StorageEnum } from '@/enums/storageEnum'
+
+const showOpenFilePicker: Function = (window as any).showOpenFilePicker
+let content = ref('')
+
+// 从sessionStorage 获取数据
+function getDataBySession () {
+  const localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as ChartEditStorageType
+  content.value = JSON.stringify(localStorageInfo, undefined, 2)
+}
+getDataBySession()
+
+// 返回父窗口
+function back() {
+  opener.name = Date.now()
+  window.open(opener.location.href, opener.name)
+}
+
+
+// 导入json文本
+async function importJSON() {
+  const files = await showOpenFilePicker()
+  const file = await files[0].getFile()
+  const fr = new FileReader()
+  fr.readAsText(file)
+  fr.onloadend = () => {
+    content.value = (fr.result || '').toString()
+  }
+}
+
+// 同步 [画布页失去焦点时同步数据到JSON页,JSON页Ctrl+S 时同步数据到画布页]
+opener.addEventListener(SavePageEnum.CHART, (e: any) => {
+  setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [e.detail])
+  content.value = JSON.stringify(e.detail, undefined, 2)
+})
+
+document.addEventListener('keydown', function (e) {
+  if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
+    e.preventDefault()
+    if (!opener) {
+      return window['$message'].error('源窗口已关闭,视图同步失败')
+    }
+    try {
+      const detail = JSON.parse(content.value)
+      delete detail.id
+      // 保持id不变
+      opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
+    } catch (e) {
+      window['$message'].error('内容格式有误')
+      console.log(e)
+    }
+  }
+})
+
+</script>
+
+<style lang="scss" scoped>
+.go-edit {
+  display: flex;
+  flex-direction: column;
+  height: 100vh;
+}
+@include deep() {
+  .go-editor-area {
+    height: calc(100% - 40px) !important;
+  }
+}
+</style>

+ 25 - 0
src/views/preview/wrapper.vue

@@ -0,0 +1,25 @@
+<template>
+  <Preview :key="key"></Preview>
+</template>
+
+<script setup lang="ts">
+import { getSessionStorageInfo } from './utils'
+import type { ChartEditStorageType } from './index.d'
+import { SavePageEnum } from '@/enums/editPageEnum'
+import { setSessionStorage } from '@/utils'
+import { StorageEnum } from '@/enums/storageEnum'
+import { ref } from 'vue'
+import Preview from './index.vue'
+
+let key = ref(Date.now())
+let localStorageInfo: ChartEditStorageType = getSessionStorageInfo() as ChartEditStorageType
+
+// 数据变更 -> 同步sessionStorage -> reload页面 (重新执行Mounted)
+;[SavePageEnum.JSON, SavePageEnum.CHART].forEach((saveEvent: string) => {
+  opener.addEventListener(saveEvent, (e: any) => {
+    setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [{ ...e.detail, id: localStorageInfo.id }])
+    key.value = Date.now()
+  })
+})
+
+</script>