perf: 优化编辑 JSON 交互功能

This commit is contained in:
奔跑的面条 2023-03-03 22:25:36 +08:00
parent 61c43df51b
commit b269933ffa
9 changed files with 158 additions and 56 deletions

View File

@ -12,7 +12,8 @@ export enum DragKeyEnum {
// 不同页面保存操作
export enum SavePageEnum {
CHART = 'SaveChart',
JSON = 'SaveJSON'
JSON = 'SaveJSON',
CLOSE = 'close'
}
// 操作枚举

View File

@ -29,7 +29,7 @@ import { ThemeColorSelect } from '@/components/Pages/ThemeColorSelect'
</script>
<style lang="scss" scoped>
$min-width: 400px;
$min-width: 520px;
@include go(header) {
&-box {
display: grid;

View File

@ -66,7 +66,8 @@ import {
List as ListIcon,
EyeOutline as EyeOutlineIcon,
EyeOffOutline as EyeOffOutlineIcon,
Albums as AlbumsIcon
Albums as AlbumsIcon,
Analytics as AnalyticsIcon
} from '@vicons/ionicons5'
import {
@ -238,7 +239,9 @@ const ionicons5 = {
EyeOutlineIcon,
EyeOffOutlineIcon,
// 图表列表
AlbumsIcon
AlbumsIcon,
// 分析
AnalyticsIcon
}
const carbon = {

View File

@ -22,7 +22,8 @@ export enum EditCanvasTypeEnum {
LOCK_SCALE = 'lockScale',
IS_CREATE = 'isCreate',
IS_DRAG = 'isDrag',
IS_SELECT = 'isSelect'
IS_SELECT = 'isSelect',
IS_CODE_EDIT="isCodeEdit"
}
// 编辑区域
@ -44,6 +45,8 @@ export type EditCanvasType = {
[EditCanvasTypeEnum.IS_DRAG]: boolean
// 框选中
[EditCanvasTypeEnum.IS_SELECT]: boolean
// 代码编辑中
[EditCanvasTypeEnum.IS_CODE_EDIT]: boolean
}
// 滤镜/背景色/宽高主题等

View File

@ -54,7 +54,9 @@ export const useChartEditStore = defineStore({
// 拖拽中
isDrag: false,
// 框选中
isSelect: false
isSelect: false,
// 代码编辑中
isCodeEdit: false
},
// 右键菜单
rightMenuShow: false,

View File

@ -1,42 +1,68 @@
import { watch } from 'vue'
import { useRoute } from 'vue-router'
import throttle from 'lodash/throttle'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSync } from '@/views/chart/hooks/useSync.hook'
import { ChartEnum } from '@/enums/pageEnum'
import { SavePageEnum } from '@/enums/editPageEnum'
import { editToJsonInterval } from '@/settings/designSetting'
import { goDialog } from '@/utils'
const { updateComponent } = useSync()
const chartEditStore = useChartEditStore()
export const syncData = () => {
goDialog({
message: '是否覆盖源视图内容,此操作不可撤回?',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: () => {
window['$message'].success('正在同步编辑器...')
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
}
})
}
// 侦听器更新
const useSyncUpdateHandle = () => {
// 定义侦听器变量
let timer: any
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
const syncData = async () => {
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
// 更新处理
const updateFn = (e: any) => {
window['$message'].success('正在进行更新...')
updateComponent(e!.detail, true)
}
// 页面关闭处理
const closeFn = () => {
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CODE_EDIT, false)
}
// 开启侦听
const use = () => {
// // 1、定时同步数据
// 定时同步数据(暂不开启)
// timer = setInterval(() => {
// // 窗口激活并且处于工作台
// document.hasFocus() && syncData()
// }, editToJsonInterval)
// 2、失焦同步数据
addEventListener('blur', syncData)
// 【监听JSON代码 刷新工作台图表】
// 失焦同步数据(暂不开启)
// addEventListener('blur', syncData)
// 监听编辑器保存事件 刷新工作台图表
addEventListener(SavePageEnum.JSON, updateFn)
// 监听编辑页关闭
addEventListener(SavePageEnum.CLOSE, throttle(closeFn, 1000))
}
// 关闭侦听
const unUse = () => {
// clearInterval(timer)
// removeEventListener('blur', syncData)
removeEventListener(SavePageEnum.JSON, updateFn)
removeEventListener('blur', syncData)
}
// 路由变更时处理
@ -48,11 +74,11 @@ const useSyncUpdateHandle = () => {
use()
}
}
return watchHandler
}
export const useSyncUpdate = () => {
const routerParamsInfo = useRoute()
watch(() => routerParamsInfo.name, useSyncUpdateHandle(), { immediate: true })
}
}

View File

@ -66,7 +66,14 @@ import { ref, computed } 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 { fetchRouteParamsLocation, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import {
fetchRouteParamsLocation,
fetchPathByName,
routerTurnByPath,
setSessionStorage,
getLocalStorage
} from '@/utils'
import { EditEnum } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum'
import { useRoute } from 'vue-router'
@ -137,8 +144,8 @@ const toolsMouseoutHandle = () => {
//
const editHandle = () => {
window['$message'].warning('将开启失焦更新')
// window['$message'].warning(' 5 ')
window['$message'].warning('请通过顶部【同步内容】按钮同步最新数据')
chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CODE_EDIT, true)
setTimeout(() => {
// id
const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href')
@ -146,7 +153,7 @@ const editHandle = () => {
const id = fetchRouteParamsLocation()
updateToSession(id)
routerTurnByPath(path, [id], undefined, true)
}, 1000)
}, 2000)
}
// SessionStorage 便
@ -169,7 +176,6 @@ const updateToSession = (id: string) => {
}
}
//
const btnList: BtnListType[] = [
{

View File

@ -1,6 +1,6 @@
<template>
<n-space class="go-mt-0">
<n-button v-for="item in btnList" :key="item.title" ghost @click="item.event">
<n-button v-for="item in comBtnList" :key="item.title" :type="item.type" ghost @click="item.event">
<template #icon>
<component :is="item.icon"></component>
</template>
@ -10,16 +10,17 @@
</template>
<script setup lang="ts">
import { shallowReactive } from 'vue'
import { computed } from 'vue'
import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
import { PreviewEnum } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum'
import { useRoute } from 'vue-router'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { syncData } from '../../ContentEdit/components/EditTools/hooks/useSyncUpdate.hook'
import { icon } from '@/plugins'
import { cloneDeep } from 'lodash'
const { BrowsersOutlineIcon, SendIcon } = icon.ionicons5
const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon } = icon.ionicons5
const chartEditStore = useChartEditStore()
const routerParamsInfo = useRoute()
@ -42,7 +43,8 @@ const previewHandle = () => {
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
} else {
sessionStorageInfo.push({
id: previewId, ...storageInfo
id: previewId,
...storageInfo
})
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
}
@ -63,7 +65,14 @@ const sendHandle = () => {
})
}
const btnList = shallowReactive([
const btnList = [
{
select: true,
title: '同步内容',
type: 'primary',
icon: renderIcon(AnalyticsIcon),
event: syncData
},
{
select: true,
title: '预览',
@ -76,9 +85,18 @@ const btnList = shallowReactive([
icon: renderIcon(SendIcon),
event: sendHandle
}
])
]
const comBtnList = computed(() => {
if (chartEditStore.getEditCanvas.isCodeEdit) {
return btnList
}
const cloneList = cloneDeep(btnList)
cloneList.shift()
return cloneList
})
</script>
<style lang="scss" scoped>
.align-center {
margin-top: -4px;

View File

@ -14,8 +14,17 @@
</n-button>
</div>
<n-space>
<n-tag :bordered="false" type="warning"> 页面失焦保存 </n-tag>
<n-tag :bordered="false" type="warning"> ctrl + s 保存 </n-tag>
<!-- 暂时关闭 -->
<!-- <n-tag :bordered="false" type="warning"> 页面失焦保存 </n-tag> -->
<n-tag :bordered="false" type="warning"> Ctrl + S 更新视图 </n-tag>
<n-button v-if="showOpenFilePicker" class="go-mr-3" size="medium" @click="updateSync">
<template #icon>
<n-icon>
<analytics-icon></analytics-icon>
</n-icon>
</template>
保存
</n-button>
</n-space>
</n-layout-header>
<n-layout-content>
@ -26,28 +35,31 @@
lineNumbers: 'on',
minimap: { enabled: true }
}"
/>
/>
</n-layout-content>
</n-layout>
</div>
</template>
<script setup lang="ts">
import { computed, ref, watch } from 'vue'
import { ref } 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, JSONStringify, JSONParse, setTitle } from '@/utils'
import { setSessionStorage, JSONStringify, JSONParse, setTitle, goDialog } from '@/utils'
import { StorageEnum } from '@/enums/storageEnum'
import { icon } from '@/plugins'
import type { ChartEditStorageType } from '../preview/index.d'
const { ChevronBackOutlineIcon, DownloadIcon } = icon.ionicons5
const { ChevronBackOutlineIcon, DownloadIcon, AnalyticsIcon } = icon.ionicons5
const showOpenFilePicker: Function = (window as any).showOpenFilePicker
const content = ref('')
window['$message'].warning('请不要刷新此窗口!')
// sessionStorage
async function getDataBySession() {
const localStorageInfo: ChartEditStorageType = await getSessionStorageInfo() as unknown as ChartEditStorageType
const localStorageInfo: ChartEditStorageType = (await getSessionStorageInfo()) as unknown as ChartEditStorageType
setTitle(`编辑-${localStorageInfo.editCanvasConfig.projectName}`)
content.value = JSONStringify(localStorageInfo)
}
@ -60,44 +72,75 @@ function back() {
}
// 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()
}
function importJSON() {
goDialog({
message: '导入数据将覆盖内容,此操作不可撤回,是否继续?',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: async () => {
try {
const files = await showOpenFilePicker()
const file = await files[0].getFile()
const fr = new FileReader()
fr.readAsText(file)
fr.onloadend = () => {
content.value = (fr.result || '').toString()
}
window['$message'].success('导入成功!')
} catch (error) {
window['$message'].error('导入失败,请检查文件是否损坏!')
console.log(error)
}
}
})
}
// [JSONJSONCtrl+S ]
//
window.opener.addEventListener(SavePageEnum.CHART, (e: any) => {
window['$message'].success('正在进行更新...')
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, [e.detail])
content.value = JSONStringify(e.detail)
})
// + =>
//
document.addEventListener('keydown', function (e) {
if (e.keyCode == 83 && (navigator.platform.match('Mac') ? e.metaKey : e.ctrlKey)) {
e.preventDefault()
updateSync()
}
})
addEventListener('blur', updateSync)
//
// addEventListener('blur', updateSync)
//
async function updateSync() {
if (!window.opener) {
return window['$message'].error('源窗口已关闭,视图同步失败')
return window['$message'].error('源窗口已关闭,视图同步失败')
}
try {
const detail = JSONParse(content.value)
delete detail.id
// id
window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
} catch (e) {
window['$message'].error('内容格式有误')
console.log(e)
goDialog({
message: '是否覆盖源视图内容? 此操作不可撤!',
isMaskClosable: true,
transformOrigin: 'center',
onPositiveCallback: () => {
try {
const detail = JSONParse(content.value)
delete detail.id
// id
window.opener.dispatchEvent(new CustomEvent(SavePageEnum.JSON, { detail }))
window['$message'].success('正在同步内容...')
} catch (e) {
window['$message'].error('内容格式有误')
console.log(e)
}
}
})
}
//
window.onbeforeunload = () => {
if (window.opener) {
window.opener.dispatchEvent(new CustomEvent(SavePageEnum.CLOSE))
}
}
</script>