!85 feat: 新增JSON编辑页面 以及 保存跨窗口同步视图更新

Merge pull request !85 from 潘潘/dev
This commit is contained in:
奔跑的面条 2022-10-27 12:27:01 +00:00 committed by Gitee
commit 179fedf622
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
9 changed files with 297 additions and 5 deletions

View File

@ -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',
// 解除锁定

View File

@ -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',

View File

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

View File

@ -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

View File

@ -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
}

View File

@ -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 = {

View File

@ -58,17 +58,107 @@
</template>
<script setup lang="ts">
import { ref, computed, h } from 'vue'
import { ref, computed, h, watch } 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, ChartEnum } 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 }])
}
}
function useSyncUpdate() {
//
let timer: any;
const updateFn = (e: any) => updateComponent(e!.detail, true, false)
const syncData = () => {
if (routerParamsInfo.name == ChartEnum.CHART_HOME_NAME) {
dispatchEvent(new CustomEvent(SavePageEnum.CHART, { detail: chartEditStore.getStorageInfo }))
}
}
//
const use = () => {
// 1
timer = setInterval(() => {
//
document.hasFocus() && syncData()
}, 5000)
// 2
addEventListener('blur', syncData)
// JSON
addEventListener(SavePageEnum.JSON, updateFn)
}
//
const unUse = () => {
clearInterval(timer)
removeEventListener(SavePageEnum.JSON, updateFn)
removeEventListener('blur', syncData)
}
//
const watchHandler = (toName: any, fromName: any) => {
if (fromName == ChartEnum.CHART_HOME_NAME) {
unUse()
}
if (toName == ChartEnum.CHART_HOME_NAME) {
use()
}
}
return watchHandler
}
watch(
() => routerParamsInfo.name,
useSyncUpdate(),
{ immediate: true }
)
//
let mouseTime: any = null
@ -95,6 +185,13 @@ const btnList: BtnListType[] = [
name: '导入',
icon: DownloadIcon
},
{
key: 'edit',
type: TypeEnum.BUTTON,
name: '编辑JSON',
icon: CodeSlashIcon,
handle: editHandle
},
{
key: 'setting',
type: TypeEnum.BUTTON,

133
src/views/edit/index.vue Normal file
View File

@ -0,0 +1,133 @@
<template>
<div class="go-edit">
<n-layout>
<n-layout-header class="go-edit-header go-px-5 go-flex-items-center" bordered>
<div>
<n-text class="go-edit-title go-mr-4">页面在线编辑器</n-text>
<n-button v-if="showOpenFilePicker" class="go-mr-3" size="medium" @click="importJSON">
<template #icon>
<n-icon>
<download-icon></download-icon>
</n-icon>
</template>
导入
</n-button>
<n-button class="go-mr-4" size="medium" @click="back">
<template #icon>
<n-icon>
<chevron-back-outline-icon></chevron-back-outline-icon>
</n-icon>
</template>
返回工作台
</n-button>
</div>
<n-tag :bordered="false" type="warning"> ctrl + s 保存/更新 </n-tag>
</n-layout-header>
<n-layout-content>
<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'
import { icon } from '@/plugins'
const { ChevronBackOutlineIcon, DownloadIcon } = icon.ionicons5
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()
}
}
// [JSONJSONCtrl+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()
updateSync()
}
})
addEventListener('blur', updateSync)
//
function updateSync() {
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;
.go-edit-header {
display: flex;
align-items: center;
height: 60px;
justify-content: space-between;
.go-edit-title {
position: relative;
bottom: 3px;
font-size: 18px;
font-weight: bold;
}
}
@include deep() {
.go-editor-area {
height: calc(100vh - 60px) !important;
}
}
}
</style>

View File

@ -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>