feat: 新增导入导出功能😍

This commit is contained in:
MTrun 2022-04-10 17:56:51 +08:00
parent aef57f13f0
commit 16bf72ac24
9 changed files with 185 additions and 42 deletions

View File

@ -22,12 +22,12 @@ export let packagesList: PackagesType = {
}
/**
* *
* @param dropData
* *
* @param targetData
*/
export const createComponent = async (dropData: ConfigType) => {
const { category, key } = dropData
const chart = await import(`./components/${dropData.package}/${category}/${key}/config.ts`)
export const createComponent = async (targetData: ConfigType) => {
const { category, key } = targetData
const chart = await import(`./components/${targetData.package}/${category}/${key}/config.ts`)
return new chart.default()
}

View File

@ -5,7 +5,6 @@ import debounce from 'lodash/debounce'
import cloneDeep from 'lodash/cloneDeep'
import { defaultTheme, globalThemeJson } from '@/settings/chartThemes/index'
import { requestInterval } from '@/settings/designSetting'
import { chartMoveDistance } from '@/settings/systemSetting'
// 记录记录
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
// 全局设置
@ -63,6 +62,7 @@ export const useChartEditStore = defineStore({
},
// 记录临时数据(复制等)
recordChart: undefined,
// -----------------------
// 画布属性(需存储给后端)
editCanvasConfig: {
// 默认宽度

View File

@ -100,6 +100,11 @@ export const useChartHistoryStore = defineStore({
clearForwardStack() {
this.forwardStack = []
},
// * 清空后退栈(保留初始化)
clearBackStack() {
const canvasHistory = this.getBackStack[0]
this.backStack = [canvasHistory]
},
// * 撤回
backAction() {
try {

View File

@ -121,7 +121,7 @@ const ChartDataSetting = loadAsyncComponent(() =>
import('./components/ChartDataSetting/index.vue')
)
//
//
const swatchesColors = [
'#232324',
'#2a2a2b',

View File

@ -0,0 +1,107 @@
import { ref, nextTick } from 'vue'
import { UploadCustomRequestOptions } from 'naive-ui'
import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { fetchChartComponent } from '@/packages/index'
import { CreateComponentType } from '@/packages/index.d'
import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
import { ChartEditStoreEnum } from '@/store/modules/chartEditStore/chartEditStore.d'
import { useChartHistoryStore } from '@/store/modules/chartHistoryStore/chartHistoryStore'
import { readFile, goDialog } from '@/utils'
import { createComponent } from '@/packages'
// 更新函数
const updateComponent = async (fileData: any, isSplace = false) => {
const chartEditStore = useChartEditStore()
const chartHistoryStore = useChartHistoryStore()
if (isSplace) {
// 清除列表
chartEditStore.componentList = []
// 清除历史记录
chartHistoryStore.clearBackStack()
chartHistoryStore.clearForwardStack()
}
// 列表组件注册
fileData.componentList.forEach(async (e: CreateComponentType) => {
if (!window['$vue'].component(e.chartConfig.chartKey)) {
window['$vue'].component(
e.chartConfig.chartKey,
fetchChartComponent(e.chartConfig)
)
}
})
// 数据赋值
for (const key in fileData) {
// 组件
if (key === ChartEditStoreEnum.COMPONENT_LIST) {
for (const comItem of fileData[key]) {
// 补充 class 上的方法
let newComponent: CreateComponentType = await createComponent(
comItem.chartConfig
)
// 不保存到记录
chartEditStore.addComponentList(
Object.assign(newComponent, comItem),
false,
true
)
}
} else {
// 非组件
Object.assign((chartEditStore as any)[key], fileData[key])
}
}
}
export const useFile = () => {
const importUploadFileListRef = ref()
const chartEditStore = useChartEditStore()
// 上传-前置
//@ts-ignore
const importBeforeUpload = ({ file }) => {
importUploadFileListRef.value = []
const type = file.file.type
if (type !== FileTypeEnum.JSON && type !== FileTypeEnum.TXT) {
window['$message'].warning('仅支持上传 【JSON】 格式文件,请重新上传!')
return false
}
return true
}
// 上传-导入
const importCustomRequest = (options: UploadCustomRequestOptions) => {
const { file } = options
nextTick(() => {
if (file.file) {
readFile(file.file).then((fileData: any) => {
goDialog({
message: '请选择导入方式:',
positiveText: '新增(可撤回)',
negativeText: '覆盖(不可撤回)',
negativeButtonProps: { type: 'info', ghost: false },
// 新增
onNegativeCallback: async () => {
fileData = JSON.parse(fileData)
await updateComponent(fileData, true)
window['$message'].success('导入成功!')
},
// 覆盖
onPositiveCallback: async () => {
fileData = JSON.parse(fileData)
await updateComponent(fileData)
window['$message'].success('导入成功!')
}
})
})
} else {
window['$message'].error('导入失败,请检查数据或联系管理员!')
}
})
}
return {
importUploadFileListRef,
importBeforeUpload,
importCustomRequest
}
}

View File

@ -0,0 +1,12 @@
export enum TypeEnum {
BOTTON = 'bottom',
IMPORTUPLOAD = 'importUpload'
}
export type BtnListType = {
key: string
type: TypeEnum
name: string
icon: any
handle?: () => void
}

View File

@ -17,14 +17,8 @@
placement="left"
>
<template #trigger>
<n-button
v-show="!isMini"
class="btn-item"
:class="[btnList.length - 1 === index && 'go-mb-0']"
:circle="isAside"
secondary
@click="item.handle"
>
<div v-show="!isMini" class="btn-item" :class="[btnList.length - 1 === index && 'go-mb-0']">
<n-button v-if="item.type === TypeEnum.BOTTON" :circle="isAside" secondary @click="item.handle">
<template #icon>
<n-icon size="22" v-if="isAside">
<component :is="item.icon"></component>
@ -33,15 +27,34 @@
</template>
<n-text depth="3" v-show="!isAside">{{ item.name }}</n-text>
</n-button>
<!-- 下载 -->
<n-upload
v-else-if="item.type === TypeEnum.IMPORTUPLOAD"
v-model:file-list="importUploadFileListRef"
:show-file-list="false"
:customRequest="importCustomRequest"
@before-upload="importBeforeUpload"
>
<n-button :circle="isAside" secondary>
<template #icon>
<n-icon size="22" v-if="isAside">
<component :is="item.icon"></component>
</n-icon>
<component v-else :is="item.icon"></component>
</template>
<n-text depth="3" v-show="!isAside">{{ item.name }}</n-text>
</n-button>
</n-upload>
</div>
</template>
<!-- 提示 -->
<span>{{ item.name }}</span>
</n-tooltip>
<!-- PawIcon -->
<n-icon
v-if="isAside"
v-show="settingStore.getChartToolsStatus === ToolsStatusEnum.ASIDE && isMini"
size="22"
v-if="isAside"
>
<PawIcon></PawIcon>
</n-icon>
@ -49,10 +62,12 @@
</template>
<script setup lang="ts">
import { ref, computed, h } from 'vue';
import { ref, computed } from 'vue';
import { useSettingStore } from '@/store/modules/settingStore/settingStore'
import { ToolsStatusEnum } from '@/store/modules/settingStore/settingStore.d'
import { importHandle, exportHandle } from './utils'
import { exportHandle } from './utils'
import { useFile } from './hooks/useFile.hooks'
import { BtnListType, TypeEnum } from './index.d'
import { icon } from '@/plugins'
const { DownloadIcon, ShareIcon, PawIcon } = icon.ionicons5
@ -63,14 +78,17 @@ let mouseTime: any = null
const isMini = ref<boolean>(true)
//
const isAside = computed(() => settingStore.getChartToolsStatus === ToolsStatusEnum.ASIDE)
//
const { importUploadFileListRef, importCustomRequest, importBeforeUpload } = useFile()
const btnList = [{
const btnList: BtnListType[] = [{
key: 'import',
type: TypeEnum.IMPORTUPLOAD,
name: '导入',
icon: DownloadIcon,
handle: importHandle
}, {
key: 'export',
type: TypeEnum.BOTTON,
name: '导出',
icon: ShareIcon,
handle: exportHandle
@ -108,7 +126,7 @@ $asideBottom: 70px;
border-radius: 25px;
border: 1px solid;
mix-blend-mode: luminosity;
transition: height ease-in 1s, padding 0.4s, bottom .4s;
transition: height ease-in 1s, padding 0.4s, bottom 0.4s;
@include filter-border-color("hover-border-color-shallow");
&.aside {
flex-direction: column;
@ -118,7 +136,6 @@ $asideBottom: 70px;
bottom: $asideBottom;
.btn-item {
margin-bottom: 10px;
padding-bottom: 6px;
/* 没生效,用上面的 go-mb-0 代替 */
&:last-child {
margin-bottom: 0;
@ -126,6 +143,7 @@ $asideBottom: 70px;
@include deep() {
.n-button__icon {
margin-right: 4px;
margin-bottom: 14px;
}
}
}

View File

@ -2,13 +2,19 @@ import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore
import { canvasCut, downloadTextFile } from '@/utils'
const chartEditStore = useChartEditStore()
// 导入
export const importHandle = () => { }
// 导出
export const exportHandle = () => {
// 取消选中
chartEditStore.setTargetSelectChart(undefined)
// 导出数据
downloadTextFile(JSON.stringify(chartEditStore.getStorageInfo || []), undefined, 'json')
downloadTextFile(
JSON.stringify(chartEditStore.getStorageInfo || [], (k, v) => {
return v === undefined ? null : v
}),
undefined,
'json'
)
// 导出图片
const ruler = document.getElementById('mb-ruler')
@ -19,6 +25,7 @@ export const exportHandle = () => {
window['$message'].error('导出失败!')
return
}
// 记录缩放比例
const scaleTemp = chartEditStore.getEditCanvas.scale
// 去除标尺Dom
@ -28,7 +35,6 @@ export const exportHandle = () => {
// 展示水印
watermark.style.display = 'block'
window['$message'].warning('生成截图和数据中, 请耐心等待...')
setTimeout(() => {
canvasCut(range, () => {
// 隐藏水印
@ -40,8 +46,3 @@ export const exportHandle = () => {
})
}, 600)
}
// 改变工具栏展示样式
export const changeTypeHandle = () => {
}

View File

@ -10,7 +10,6 @@ export const useComInstall = (localStorageInfo: ChartEditStorageType) => {
const intervalTiming = setInterval(() => {
if (window['$vue'].component) {
clearInterval(intervalTiming)
show.value = true
localStorageInfo.componentList.forEach(async (e: CreateComponentType) => {
if (!window['$vue'].component(e.chartConfig.chartKey)) {
window['$vue'].component(
@ -19,6 +18,7 @@ export const useComInstall = (localStorageInfo: ChartEditStorageType) => {
)
}
})
show.value = true
}
}, 200)