Demo:支持导入导出Excel

This commit is contained in:
街角小林
2024-09-11 17:41:57 +08:00
parent 9b7305de1e
commit f4d84aeb55
12 changed files with 122 additions and 87 deletions

View File

@@ -1,8 +1,8 @@
@font-face {
font-family: "iconfont"; /* Project id 2479351 */
src: url('iconfont.woff2?t=1719815803051') format('woff2'),
url('iconfont.woff?t=1719815803051') format('woff'),
url('iconfont.ttf?t=1719815803051') format('truetype');
src: url('iconfont.woff2?t=1726022313538') format('woff2'),
url('iconfont.woff?t=1726022313538') format('woff'),
url('iconfont.ttf?t=1726022313538') format('truetype');
}
.iconfont {
@@ -13,6 +13,14 @@
-moz-osx-font-smoothing: grayscale;
}
.iconfile-excel:before {
content: "\e7b7";
}
.iconfreemind:before {
content: "\e97d";
}
.iconwaikuang:before {
content: "\e640";
}

View File

@@ -499,8 +499,14 @@ export const downTypeList = [
{
name: 'FreeMind',
type: 'mm',
icon: 'iconTXT',
icon: 'iconfreemind',
desc: 'FreeMind software format'
},
{
name: 'Excel',
type: 'xlsx',
icon: 'iconfile-excel',
desc: 'Excel software format'
}
]

View File

@@ -593,8 +593,14 @@ export const downTypeList = [
{
name: 'FreeMind',
type: 'mm',
icon: 'iconTXT',
icon: 'iconfreemind',
desc: 'FreeMind软件格式'
},
{
name: 'Excel',
type: 'xlsx',
icon: 'iconfile-excel',
desc: 'Excel软件格式'
}
]

View File

@@ -157,8 +157,9 @@ export default {
import: {
title: 'Import',
selectFile: 'Select file',
supportFile: 'Support .smm、.json、.xmind、.xlsx、.md、 .mm file',
enableFileTip: 'Please select .smm、.json、.xmind、.xlsx、.md、 .mm file',
support: 'Support',
file: 'file',
pleaseSelect: 'Please select',
maxFileNum: 'At most one file can be selected',
notSelectTip: 'Please select the file to import',
fileContentError: 'The file content is incorrect',

View File

@@ -155,8 +155,9 @@ export default {
import: {
title: '导入',
selectFile: '选取文件',
supportFile: '支持.smm、.json、.xmind、.xlsx、.md、 .mm文件',
enableFileTip: '请选择.smm、.json、.xmind、.xlsx、.md、 .mm文件',
support: '支持',
file: '文件',
pleaseSelect: '请选择',
maxFileNum: '最多只能选择一个文件',
notSelectTip: '请选择要导入的文件',
fileContentError: '文件内容有误',

View File

@@ -80,7 +80,10 @@ import OuterFrame from 'simple-mind-map/src/plugins/OuterFrame.js'
// 编号插件,该插件为付费插件,详情请查看开发文档
// import Numbers from 'simple-mind-map-plugin-numbers'
// Freemind软件格式导入导出插件该插件为付费插件详情请查看开发文档
import Freemind from 'simple-mind-map-plugin-freemind'
// import Freemind from 'simple-mind-map-plugin-freemind'
// Excel软件格式导入导出插件该插件为付费插件详情请查看开发文档
// import Excel from 'simple-mind-map-plugin-excel'
// npm link simple-mind-map-plugin-excel simple-mind-map-plugin-freemind simple-mind-map-plugin-numbers simple-mind-map-plugin-notation simple-mind-map-plugin-handdrawnlikestyle simple-mind-map
import OutlineSidebar from './OutlineSidebar'
import Style from './Style'
import BaseStyle from './BaseStyle'
@@ -137,7 +140,6 @@ MindMap.usePlugin(MiniMap)
.usePlugin(RainbowLines)
.usePlugin(Demonstrate)
.usePlugin(OuterFrame)
.usePlugin(Freemind)
// .usePlugin(Cooperate) // 协同插件
// 注册自定义主题
@@ -566,6 +568,16 @@ export default {
this.mindMap.addPlugin(Numbers)
this.$store.commit('setSupportNumbers', true)
}
if (typeof Freemind !== 'undefined') {
this.mindMap.addPlugin(Freemind)
this.$store.commit('setSupportFreemind', true)
Vue.prototype.Freemind = Freemind
}
if (typeof Excel !== 'undefined') {
this.mindMap.addPlugin(Excel)
this.$store.commit('setSupportExcel', true)
Vue.prototype.Excel = Excel
}
this.mindMap.keyCommand.addShortcut('Control+s', () => {
this.manualSave()
})

View File

@@ -126,11 +126,23 @@ export default {
computed: {
...mapState({
openNodeRichText: state => state.localConfig.openNodeRichText,
isDark: state => state.localConfig.isDark
isDark: state => state.localConfig.isDark,
supportFreemind: state => state.supportFreemind,
supportExcel: state => state.supportExcel
}),
downTypeList() {
return downTypeList[this.$i18n.locale] || downTypeList.zh
const list = downTypeList[this.$i18n.locale] || downTypeList.zh
return list.filter(item => {
if (item.type === 'mm') {
return this.supportFreemind
}
if (item.type === 'xlsx') {
return this.supportExcel
} else {
return true
}
})
}
},
created() {

View File

@@ -9,7 +9,7 @@
<el-upload
ref="upload"
action="x"
accept=".smm,.json,.xmind,.xlsx,.md,.mm"
:accept="supportFileStr"
:file-list="fileList"
:auto-upload="false"
:multiple="false"
@@ -22,7 +22,7 @@
$t('import.selectFile')
}}</el-button>
<div slot="tip" class="el-upload__tip">
{{ $t('import.supportFile') }}
{{ $t('import.support') }}{{ supportFileStr }}{{ $t('import.file') }}
</div>
</el-upload>
<span slot="footer" class="dialog-footer">
@@ -59,10 +59,8 @@
<script>
import xmind from 'simple-mind-map/src/parse/xmind.js'
import markdown from 'simple-mind-map/src/parse/markdown.js'
import { freemindToSmm } from 'simple-mind-map-plugin-freemind/freemindTo.js'
import { fileToBuffer } from '@/utils'
import { read, utils } from 'xlsx'
import { mapMutations } from 'vuex'
import { mapMutations, mapState } from 'vuex'
import Vue from 'vue'
/**
* @Author: 王林
@@ -81,6 +79,22 @@ export default {
canvasList: []
}
},
computed: {
...mapState({
supportFreemind: state => state.supportFreemind,
supportExcel: state => state.supportExcel
}),
supportFileStr() {
let res = '.smm,.json,.xmind,.md'
if (this.supportFreemind) {
res += ',.mm'
}
if (this.supportExcel) {
res += ',.xlsx'
}
return res
}
},
watch: {
dialogVisible(val, oldVal) {
if (!val && oldVal) {
@@ -105,12 +119,20 @@ export default {
this.dialogVisible = true
},
getRegexp() {
return new RegExp(
`\.(smm|json|xmind|md${this.supportFreemind ? '|mm' : ''}${
this.supportExcel ? '|xlsx' : ''
})$`
)
},
// 检查url中是否操作需要打开的文件
async handleFileURL() {
try {
const fileURL = this.$route.query.fileURL
if (!fileURL) return
const macth = /\.(smm|json|xmind|md|xlsx|mm)$/.exec(fileURL)
const macth = this.getRegexp().exec(fileURL)
if (!macth) {
return
}
@@ -138,9 +160,12 @@ export default {
// 文件选择
onChange(file) {
let reg = /\.(smm|xmind|json|xlsx|md|mm)$/
if (!reg.test(file.name)) {
this.$message.error(this.$t('import.enableFileTip'))
if (!this.getRegexp().test(file.name)) {
this.$message.error(
this.$t('import.pleaseSelect') +
this.supportFileStr +
this.$t('import.file')
)
this.fileList = []
} else {
this.fileList.push(file)
@@ -226,18 +251,21 @@ export default {
fileReader.readAsText(file.raw)
fileReader.onload = async evt => {
try {
const data = await freemindToSmm(evt.target.result, {
// withStyle: true,
transformImg: image => {
return new Promise(resolve => {
if (/^https?:\/\//.test(image)) {
resolve({ url: image })
} else {
resolve(null)
}
})
const data = await Vue.prototype.Freemind.freemindToSmm(
evt.target.result,
{
// withStyle: true,
transformImg: image => {
return new Promise(resolve => {
if (/^https?:\/\//.test(image)) {
resolve({ url: image })
} else {
resolve(null)
}
})
}
}
})
)
this.$bus.$emit('setData', data)
this.$message.success(this.$t('import.importSuccess'))
} catch (error) {
@@ -265,59 +293,8 @@ export default {
// 处理.xlsx文件
async handleExcel(file) {
try {
const wb = read(await fileToBuffer(file.raw))
const data = utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], {
header: 1
})
if (data.length <= 0) {
return
}
let max = 0
data.forEach(arr => {
if (arr.length > max) {
max = arr.length
}
})
let layers = []
let walk = layer => {
if (!layers[layer]) {
layers[layer] = []
}
for (let i = 0; i < data.length; i++) {
if (data[i][layer]) {
let node = {
data: {
text: data[i][layer]
},
children: [],
_row: i
}
layers[layer].push(node)
}
}
if (layer < max - 1) {
walk(layer + 1)
}
}
walk(0)
let getParent = (arr, row) => {
for (let i = arr.length - 1; i >= 0; i--) {
if (row >= arr[i]._row) {
return arr[i]
}
}
}
for (let i = 1; i < layers.length; i++) {
let arr = layers[i]
for (let j = 0; j < arr.length; j++) {
let item = arr[j]
let parent = getParent(layers[i - 1], item._row)
if (parent) {
parent.children.push(item)
}
}
}
this.$bus.$emit('setData', layers[0][0])
const res = await Vue.prototype.Excel.excelTo(file.raw)
this.$bus.$emit('setData', res)
this.$message.success(this.$t('import.importSuccess'))
} catch (error) {
console.log(error)

View File

@@ -31,6 +31,8 @@ const store = new Vuex.Store({
supportHandDrawnLikeStyle: false, // 是否支持设置手绘风格
supportMark: false, // 是否支持标记
supportNumbers: false, // 是否支持编号
supportFreemind: false, // 是否支持Freemind插件
supportExcel: false, // 是否支持Excel插件
isDragOutlineTreeNode: false // 当前是否正在拖拽大纲树的节点
},
mutations: {
@@ -93,6 +95,16 @@ const store = new Vuex.Store({
state.supportNumbers = data
},
// 设置是否支持Freemind插件
setSupportFreemind(state, data) {
state.supportFreemind = data
},
// 设置是否支持Excel插件
setSupportExcel(state, data) {
state.supportExcel = data
},
// 设置树节点拖拽
setIsDragOutlineTreeNode(state, data) {
state.isDragOutlineTreeNode = data