Merge branch 'dev'

This commit is contained in:
奔跑的面条 2023-03-04 17:05:46 +08:00
commit b94b44090b
19 changed files with 491 additions and 69 deletions

View File

@ -172,7 +172,9 @@ export const customizeHttp = (targetParams: RequestConfigType, globalParams: Req
case RequestBodyEnum.JSON: case RequestBodyEnum.JSON:
headers['Content-Type'] = ContentTypeEnum.JSON headers['Content-Type'] = ContentTypeEnum.JSON
data = translateStr(JSON.parse(targetRequestParams.Body['json'])) //json对象也能使用'javasctipt:'来动态拼接参数
data = translateStr(targetRequestParams.Body['json'])
if(typeof data === 'string') data = JSON.parse(data)
// json 赋值给 data // json 赋值给 data
break break

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

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

View File

@ -7,15 +7,15 @@ export enum BaseEvent {
// 移入 // 移入
ON_MOUSE_ENTER = 'mouseenter', ON_MOUSE_ENTER = 'mouseenter',
// 移出 // 移出
ON_MOUSE_LEAVE = 'mouseleave', ON_MOUSE_LEAVE = 'mouseleave'
} }
// vue3 生命周期事件 // vue3 生命周期事件
export enum EventLife { export enum EventLife {
// 渲染之后 // 渲染之后
VNODE_MOUNTED = 'vnodeMounted', VNODE_MOUNTED = 'vnodeMounted',
// 渲染之前 // 渲染之前
VNODE_BEFORE_MOUNT = 'vnodeBeforeMount', VNODE_BEFORE_MOUNT = 'vnodeBeforeMount'
} }
// 内置字符串函数对象列表 // 内置字符串函数对象列表
@ -28,4 +28,9 @@ export const excludeParseEventKeyList = [
BaseEvent.ON_MOUSE_LEAVE, BaseEvent.ON_MOUSE_LEAVE,
//过滤器 //过滤器
'filter' 'filter'
] ]
// 内置字符串函数键值列表
export const excludeParseEventValueList = [
// 请求里的函数语句
'javascript:'
]

View File

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

View File

@ -59,13 +59,14 @@ const getGeojson = (regionId: string) => {
} }
// //
registerMap(props.chartConfig.option.mapRegion.adcode, { geoJSON: {} as any, specialAreas: {} }) registerMap(`${props.chartConfig.option.mapRegion.adcode}`, { geoJSON: {} as any, specialAreas: {} })
// china // china
const registerMapInitAsync = async () => { const registerMapInitAsync = async () => {
await nextTick() await nextTick()
if (props.chartConfig.option.mapRegion.adcode != 'china') { const adCode = `${props.chartConfig.option.mapRegion.adcode}`;
await getGeojson(props.chartConfig.option.mapRegion.adcode) if (adCode !== 'china') {
await getGeojson(adCode)
} else { } else {
await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands) await hainanLandsHandle(props.chartConfig.option.mapRegion.showHainanIsLands)
} }
@ -127,7 +128,7 @@ watch(
// //
watch( watch(
() => props.chartConfig.option.mapRegion.adcode, () => `${props.chartConfig.option.mapRegion.adcode}`,
async newData => { async newData => {
try { try {
await getGeojson(newData) await getGeojson(newData)

View File

@ -0,0 +1,44 @@
import { PublicConfigClass } from '@/packages/public'
import { CreateComponentType } from '@/packages/index.d'
import { ImageCarouselConfig } from './index'
import cloneDeep from 'lodash/cloneDeep'
import logo from '@/assets/logo.png'
export const option = {
// 图片资源列表
dataset: [
'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel1.jpeg',
'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel2.jpeg',
'https://naive-ui.oss-cn-beijing.aliyuncs.com/carousel-img/carousel3.jpeg',
],
// 自动播放
autoplay: true,
// 自动播放的间隔(豪秒)
interval: 5000,
// 每页显示的图片数量
slidesPerview: 1,
// 轮播方向
direction: "horizontal",
// 拖曳切换
draggable: true,
// 居中显示
centeredSlides: false,
// 过渡效果
effect: "slide",
// 是否显示指示点
showDots: true,
// 指示器样式
dotType: "dot",
// 指示器位置
dotPlacement: "bottom",
// 显示箭头
showArrow: false,
// 图片样式
fit: "contain",
}
export default class Config extends PublicConfigClass implements CreateComponentType {
public key = ImageCarouselConfig.key
public chartConfig = cloneDeep(ImageCarouselConfig)
public option = cloneDeep(option)
}

View File

@ -0,0 +1,168 @@
<template>
<collapse-item name="路径" :expanded="true">
<setting-item v-for="(item, index) in optionData.dataset" :key="index">
<n-input-group>
<n-input v-model:value="optionData.dataset[index]" size="small" placeholder="请输入图片地址"></n-input>
<n-button ghost @click="optionData.dataset.splice(index, 1)"> - </n-button>
</n-input-group>
</setting-item>
<setting-item>
<n-button size="small" @click="optionData.dataset.push('')"> + 新增</n-button>
</setting-item>
</collapse-item>
<collapse-item name="轮播属性" :expanded="true">
<setting-item-box name="播放器">
<setting-item>
<n-space>
<n-switch v-model:value="optionData.autoplay" size="small" />
<n-text>自动播放</n-text>
</n-space>
</setting-item>
<!-- 开启自动播放时设置间隔时间 -->
<setting-item name="间隔时间">
<n-input-number v-model:value="optionData.interval" size="small" placeholder="">
<template #suffix> 毫秒 </template>
</n-input-number>
</setting-item>
<setting-item name="轮播方向">
<n-select v-model:value="optionData.direction" :options="directions" placeholder="选择方向" />
</setting-item>
<setting-item name="过渡效果">
<n-select v-model:value="optionData.effect" :options="effects" placeholder="效果" />
</setting-item>
<setting-item name="每页数量">
<n-input-number v-model:value="optionData.slidesPerview" size="small" placeholder=""></n-input-number>
</setting-item>
<setting-item>
<n-space>
<n-switch v-model:value="optionData.centeredSlides" size="small" />
<n-text>居中显示</n-text>
</n-space>
</setting-item>
<setting-item name="图片样式">
<n-select v-model:value="optionData.fit" :options="fitList" placeholder="样式" />
</setting-item>
</setting-item-box>
<setting-item-box name="指示器">
<setting-item name="样式">
<n-select v-model:value="optionData.dotType" :options="dotTypes" placeholder="选择样式" />
</setting-item>
<setting-item name="位置">
<n-select v-model:value="optionData.dotPlacement" :options="dotPlacements" placeholder="选择位置" />
</setting-item>
<setting-item>
<n-space>
<n-switch v-model:value="optionData.showDots" size="small" />
<n-text>显示</n-text>
</n-space>
</setting-item>
<setting-item>
<n-space>
<n-switch v-model:value="optionData.showArrow" size="small" />
<n-text>箭头</n-text>
</n-space>
</setting-item>
<setting-item>
<n-space>
<n-switch v-model:value="optionData.draggable" size="small" />
<n-text>拖曳切换</n-text>
</n-space>
</setting-item>
</setting-item-box>
</collapse-item>
</template>
<script setup lang="ts">
import { PropType } from 'vue'
import { option } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
const props = defineProps({
optionData: {
type: Object as PropType<typeof option>,
required: true
}
})
//
const dotTypes = [
{
label: '点',
value: 'dot'
},
{
label: '线',
value: 'line'
}
]
const directions = [
{
label: '水平方向',
value: 'horizontal'
},
{
label: '垂直方向',
value: 'vertical'
}
]
const effects = [
{
label: 'slide',
value: 'slide'
},
{
label: 'fade',
value: 'fade'
},
{
label: 'card',
value: 'card'
},
{
label: 'custom',
value: 'custom'
}
]
const dotPlacements = [
{
label: '上边',
value: 'top'
},
{
label: '下边',
value: 'bottom'
},
{
label: '左边',
value: 'left'
},
{
label: '右边',
value: 'right'
}
]
//
const fitList = [
{
value: 'fill',
label: 'fill'
},
{
value: 'contain',
label: 'contain'
},
{
value: 'cover',
label: 'cover'
},
{
value: 'scale-down',
label: 'scale-down'
},
{
value: 'none',
label: 'none'
}
]
</script>

View File

@ -0,0 +1,14 @@
import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
import { ChatCategoryEnum, ChatCategoryEnumName } from '../../index.d'
export const ImageCarouselConfig: ConfigType = {
key: 'ImageCarousel',
chartKey: 'VImageCarousel',
conKey: 'VCImageCarousel',
title: '轮播图',
category: ChatCategoryEnum.MORE,
categoryName: ChatCategoryEnumName.MORE,
package: PackagesCategoryEnum.INFORMATIONS,
chartFrame: ChartFrameEnum.NAIVE_UI,
image: 'photo_carousel.png'
}

View File

@ -0,0 +1,78 @@
<template>
<div>
<n-carousel
:autoplay="autoplay"
:interval="interval"
:centered-slides="centeredSlides"
:direction="direction"
:dot-placement="dotPlacement"
:dot-type="dotType"
:draggable="draggable"
:effect="effect"
:slides-per-view="slidesPerview"
:show-arrow="showArrow"
:show-dots="showDots"
>
<n-image
v-for="(url, index) in option.dataset"
preview-disabled
:key="index"
:object-fit="fit"
:src="url"
:fallback-src="requireErrorImg()"
:width="w"
:height="h"
></n-image>
</n-carousel>
</div>
</template>
<script setup lang="ts">
import { PropType, toRefs, shallowReactive, watch } from 'vue'
import { CreateComponentType } from '@/packages/index.d'
import { requireErrorImg } from '@/utils'
import { useChartDataFetch } from '@/hooks'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { option as configOption } from './config'
const props = defineProps({
chartConfig: {
type: Object as PropType<CreateComponentType>,
required: true
}
})
const option = shallowReactive({
dataset: configOption.dataset
})
const { w, h } = toRefs(props.chartConfig.attr)
const {
autoplay,
interval,
slidesPerview,
direction,
draggable,
centeredSlides,
effect,
dotType,
dotPlacement,
showArrow,
showDots,
fit
} = toRefs(props.chartConfig.option)
watch(
() => props.chartConfig.option.dataset,
(newData: any) => {
option.dataset = newData
},
{
immediate: true,
deep: false
}
)
useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
option.dataset = newData
})
</script>

View File

@ -1,7 +1,8 @@
import { ImageConfig } from './Image/index' import { ImageConfig } from './Image/index'
import { ImageCarouselConfig } from './ImageCarousel/index'
import { IframeConfig } from './Iframe/index' import { IframeConfig } from './Iframe/index'
import { VideoConfig } from './Video/index' import { VideoConfig } from './Video/index'
import { WordCloudConfig } from './WordCloud/index' import { WordCloudConfig } from './WordCloud/index'
import { CarouselConfig } from './Carousel/index' import { CarouselConfig } from './Carousel/index'
export default [WordCloudConfig, ImageConfig, VideoConfig, IframeConfig, CarouselConfig] export default [ImageConfig, ImageCarouselConfig, VideoConfig, IframeConfig, WordCloudConfig]

View File

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

View File

@ -22,7 +22,8 @@ export enum EditCanvasTypeEnum {
LOCK_SCALE = 'lockScale', LOCK_SCALE = 'lockScale',
IS_CREATE = 'isCreate', IS_CREATE = 'isCreate',
IS_DRAG = 'isDrag', 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_DRAG]: boolean
// 框选中 // 框选中
[EditCanvasTypeEnum.IS_SELECT]: boolean [EditCanvasTypeEnum.IS_SELECT]: boolean
// 代码编辑中
[EditCanvasTypeEnum.IS_CODE_EDIT]: boolean
} }
// 滤镜/背景色/宽高主题等 // 滤镜/背景色/宽高主题等

View File

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

View File

@ -10,7 +10,7 @@ import cloneDeep from 'lodash/cloneDeep'
import { WinKeyboard } from '@/enums/editPageEnum' import { WinKeyboard } from '@/enums/editPageEnum'
import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum' import { RequestHttpIntervalEnum, RequestParamsObjType } from '@/enums/httpEnum'
import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d' import { CreateComponentType, CreateComponentGroupType } from '@/packages/index.d'
import { excludeParseEventKeyList } from '@/enums/eventEnum' import { excludeParseEventKeyList, excludeParseEventValueList } from '@/enums/eventEnum'
/** /**
* * * *
@ -320,10 +320,17 @@ export const JSONStringify = <T>(data: T) => {
*/ */
export const JSONParse = (data: string) => { export const JSONParse = (data: string) => {
return JSON.parse(data, (k, v) => { return JSON.parse(data, (k, v) => {
// 过滤函数字符串
if (excludeParseEventKeyList.includes(k)) return v if (excludeParseEventKeyList.includes(k)) return v
// 过滤函数值表达式
if (typeof v === 'string') {
const someValue = excludeParseEventValueList.some(excludeValue => v.indexOf(excludeValue) > -1)
if (someValue) return v
}
// 还原函数值
if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) { if (typeof v === 'string' && v.indexOf && (v.indexOf('function') > -1 || v.indexOf('=>') > -1)) {
return eval(`(function(){return ${v}})()`) return eval(`(function(){return ${v}})()`)
} else if (typeof v === 'string' && v.indexOf && (v.indexOf('return ') > -1)) { } else if (typeof v === 'string' && v.indexOf && v.indexOf('return ') > -1) {
const baseLeftIndex = v.indexOf('(') const baseLeftIndex = v.indexOf('(')
if (baseLeftIndex > -1) { if (baseLeftIndex > -1) {
const newFn = `function ${v.substring(baseLeftIndex)}` const newFn = `function ${v.substring(baseLeftIndex)}`
@ -340,4 +347,4 @@ export const JSONParse = (data: string) => {
*/ */
export const setTitle = (title?: string) => { export const setTitle = (title?: string) => {
title && (document.title = title) title && (document.title = title)
} }

View File

@ -1,42 +1,68 @@
import { watch } from 'vue' import { watch } from 'vue'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import throttle from 'lodash/throttle'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { EditCanvasTypeEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useSync } from '@/views/chart/hooks/useSync.hook' import { useSync } from '@/views/chart/hooks/useSync.hook'
import { ChartEnum } from '@/enums/pageEnum' import { ChartEnum } from '@/enums/pageEnum'
import { SavePageEnum } from '@/enums/editPageEnum' import { SavePageEnum } from '@/enums/editPageEnum'
import { editToJsonInterval } from '@/settings/designSetting' import { editToJsonInterval } from '@/settings/designSetting'
import { goDialog } from '@/utils'
const { updateComponent } = useSync() const { updateComponent } = useSync()
const chartEditStore = useChartEditStore() 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 = () => { const useSyncUpdateHandle = () => {
// 定义侦听器变量 // 定义侦听器变量
let timer: any 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 = () => { const use = () => {
// // 1、定时同步数据 // 定时同步数据(暂不开启)
// timer = setInterval(() => { // timer = setInterval(() => {
// // 窗口激活并且处于工作台 // // 窗口激活并且处于工作台
// document.hasFocus() && syncData() // document.hasFocus() && syncData()
// }, editToJsonInterval) // }, editToJsonInterval)
// 2、失焦同步数据
addEventListener('blur', syncData)
// 【监听JSON代码 刷新工作台图表】 // 失焦同步数据(暂不开启)
// addEventListener('blur', syncData)
// 监听编辑器保存事件 刷新工作台图表
addEventListener(SavePageEnum.JSON, updateFn) addEventListener(SavePageEnum.JSON, updateFn)
// 监听编辑页关闭
addEventListener(SavePageEnum.CLOSE, throttle(closeFn, 1000))
} }
// 关闭侦听 // 关闭侦听
const unUse = () => { const unUse = () => {
// clearInterval(timer) // clearInterval(timer)
// removeEventListener('blur', syncData)
removeEventListener(SavePageEnum.JSON, updateFn) removeEventListener(SavePageEnum.JSON, updateFn)
removeEventListener('blur', syncData)
} }
// 路由变更时处理 // 路由变更时处理
@ -48,11 +74,11 @@ const useSyncUpdateHandle = () => {
use() use()
} }
} }
return watchHandler return watchHandler
} }
export const useSyncUpdate = () => { export const useSyncUpdate = () => {
const routerParamsInfo = useRoute() const routerParamsInfo = useRoute()
watch(() => routerParamsInfo.name, useSyncUpdateHandle(), { immediate: true }) 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 { useSettingStore } from '@/store/modules/settingStore/settingStore'
import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d' import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 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 { EditEnum } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
@ -137,8 +144,8 @@ const toolsMouseoutHandle = () => {
// //
const editHandle = () => { const editHandle = () => {
window['$message'].warning('将开启失焦更新') window['$message'].warning('请通过顶部【同步内容】按钮同步最新数据')
// window['$message'].warning(' 5 ') chartEditStore.setEditCanvas(EditCanvasTypeEnum.IS_CODE_EDIT, true)
setTimeout(() => { setTimeout(() => {
// id // id
const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href') const path = fetchPathByName(EditEnum.CHART_EDIT_NAME, 'href')
@ -146,7 +153,7 @@ const editHandle = () => {
const id = fetchRouteParamsLocation() const id = fetchRouteParamsLocation()
updateToSession(id) updateToSession(id)
routerTurnByPath(path, [id], undefined, true) routerTurnByPath(path, [id], undefined, true)
}, 1000) }, 2000)
} }
// SessionStorage 便 // SessionStorage 便
@ -169,7 +176,6 @@ const updateToSession = (id: string) => {
} }
} }
// //
const btnList: BtnListType[] = [ const btnList: BtnListType[] = [
{ {

View File

@ -1,6 +1,6 @@
<template> <template>
<n-space class="go-mt-0"> <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> <template #icon>
<component :is="item.icon"></component> <component :is="item.icon"></component>
</template> </template>
@ -10,16 +10,17 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { shallowReactive } from 'vue' import { computed } from 'vue'
import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils' import { renderIcon, goDialog, fetchPathByName, routerTurnByPath, setSessionStorage, getLocalStorage } from '@/utils'
import { PreviewEnum } from '@/enums/pageEnum' import { PreviewEnum } from '@/enums/pageEnum'
import { StorageEnum } from '@/enums/storageEnum' import { StorageEnum } from '@/enums/storageEnum'
import { useRoute } from 'vue-router' import { useRoute } from 'vue-router'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore' 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 { icon } from '@/plugins'
import { cloneDeep } from 'lodash'
const { BrowsersOutlineIcon, SendIcon } = icon.ionicons5 const { BrowsersOutlineIcon, SendIcon, AnalyticsIcon } = icon.ionicons5
const chartEditStore = useChartEditStore() const chartEditStore = useChartEditStore()
const routerParamsInfo = useRoute() const routerParamsInfo = useRoute()
@ -42,7 +43,8 @@ const previewHandle = () => {
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo)
} else { } else {
sessionStorageInfo.push({ sessionStorageInfo.push({
id: previewId, ...storageInfo id: previewId,
...storageInfo
}) })
setSessionStorage(StorageEnum.GO_CHART_STORAGE_LIST, sessionStorageInfo) 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, select: true,
title: '预览', title: '预览',
@ -76,9 +85,18 @@ const btnList = shallowReactive([
icon: renderIcon(SendIcon), icon: renderIcon(SendIcon),
event: sendHandle event: sendHandle
} }
]) ]
const comBtnList = computed(() => {
if (chartEditStore.getEditCanvas.isCodeEdit) {
return btnList
}
const cloneList = cloneDeep(btnList)
cloneList.shift()
return cloneList
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.align-center { .align-center {
margin-top: -4px; margin-top: -4px;

View File

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