mirror of
https://github.com/wanglin2/mind-map.git
synced 2026-02-17 22:08:25 +08:00
Merge branch 'feature' into main
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
const path = require('path')
|
||||
const fs = require('fs')
|
||||
const hljs = require('highlight.js')
|
||||
const md = require('markdown-it')({
|
||||
html: true,
|
||||
xhtmlOut: true,
|
||||
highlight: function(str, lang) {
|
||||
if (lang && hljs.getLanguage(lang)) {
|
||||
try {
|
||||
return (
|
||||
'<pre class="hljs"><code>' +
|
||||
hljs.highlight(str, {
|
||||
language: lang,
|
||||
ignoreIllegals: true
|
||||
}).value +
|
||||
'</code></pre>'
|
||||
)
|
||||
} catch (__) {}
|
||||
}
|
||||
|
||||
return (
|
||||
'<pre class="hljs"><code>' + md.utils.escapeHtml(str) + '</code></pre>'
|
||||
)
|
||||
}
|
||||
}).use(require('markdown-it-checkbox'))
|
||||
|
||||
const templatePath = path.join(__dirname, '../src/pages/Doc/Template.vue')
|
||||
|
||||
exports.transformMdToVue = (content) => {
|
||||
let result = md.render(content)
|
||||
let template = fs.readFileSync(templatePath, 'utf-8')
|
||||
return template.replace('$$$$', result)
|
||||
}
|
||||
BIN
web/src/assets/avatar/Lawliet.jpg
Normal file
BIN
web/src/assets/avatar/Lawliet.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 50 KiB |
BIN
web/src/assets/avatar/一叶孤舟.jpg
Normal file
BIN
web/src/assets/avatar/一叶孤舟.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 34 KiB |
@@ -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";
|
||||
}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -85,12 +85,14 @@ export const formulaList = [
|
||||
'\\begin{cases}3x + 5y + z \\\\7x - 2y + 4z \\\\-6x + 3y + 2z\\end{cases}'
|
||||
]
|
||||
|
||||
// 支持某种连线类型的结构
|
||||
export const supportLineStyleLayoutsMap = {
|
||||
curve: [
|
||||
'logicalStructure',
|
||||
'logicalStructureLeft',
|
||||
'mindMap',
|
||||
'verticalTimeline'
|
||||
'verticalTimeline',
|
||||
'organizationStructure'
|
||||
],
|
||||
direct: [
|
||||
'logicalStructure',
|
||||
@@ -101,6 +103,7 @@ export const supportLineStyleLayoutsMap = {
|
||||
]
|
||||
}
|
||||
|
||||
// 直线模式支持设置圆角的结构
|
||||
export const supportLineRadiusLayouts = [
|
||||
'logicalStructure',
|
||||
'logicalStructureLeft',
|
||||
@@ -108,6 +111,7 @@ export const supportLineRadiusLayouts = [
|
||||
'verticalTimeline'
|
||||
]
|
||||
|
||||
// 支持只显示底边直线风格的结构
|
||||
export const supportNodeUseLineStyleLayouts = [
|
||||
'logicalStructure',
|
||||
'logicalStructureLeft',
|
||||
@@ -116,10 +120,12 @@ export const supportNodeUseLineStyleLayouts = [
|
||||
'organizationStructure'
|
||||
]
|
||||
|
||||
// 支持曲线模式下,根节点样式和其他节点样式保持一致的结构
|
||||
export const supportRootLineKeepSameInCurveLayouts = [
|
||||
'logicalStructure',
|
||||
'logicalStructureLeft',
|
||||
'mindMap'
|
||||
'mindMap',
|
||||
'organizationStructure'
|
||||
]
|
||||
|
||||
// 彩虹线条配置
|
||||
|
||||
@@ -495,6 +495,18 @@ export const downTypeList = [
|
||||
type: 'txt',
|
||||
icon: 'iconTXT',
|
||||
desc: 'Plain text file'
|
||||
},
|
||||
{
|
||||
name: 'FreeMind',
|
||||
type: 'mm',
|
||||
icon: 'iconfreemind',
|
||||
desc: 'FreeMind software format'
|
||||
},
|
||||
{
|
||||
name: 'Excel',
|
||||
type: 'xlsx',
|
||||
icon: 'iconfile-excel',
|
||||
desc: 'Excel software format'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -557,3 +569,55 @@ export const numberLevelList = [
|
||||
value: 0
|
||||
}
|
||||
]
|
||||
|
||||
// 背景渐变方向
|
||||
export const linearGradientDirList = [
|
||||
{
|
||||
name: 'Left to right',
|
||||
value: '1',
|
||||
start: [0, 0],
|
||||
end: [1, 0]
|
||||
},
|
||||
{
|
||||
name: 'Right to left',
|
||||
value: '2',
|
||||
start: [1, 0],
|
||||
end: [0, 0]
|
||||
},
|
||||
{
|
||||
name: 'Top to bottom',
|
||||
value: '3',
|
||||
start: [0, 0],
|
||||
end: [0, 1]
|
||||
},
|
||||
{
|
||||
name: 'Bottom to top',
|
||||
value: '4',
|
||||
start: [0, 1],
|
||||
end: [0, 0]
|
||||
},
|
||||
{
|
||||
name: 'Left top to right bottom',
|
||||
value: '5',
|
||||
start: [0, 0],
|
||||
end: [1, 1]
|
||||
},
|
||||
{
|
||||
name: 'Left bottom to right top',
|
||||
value: '6',
|
||||
start: [0, 1],
|
||||
end: [1, 0]
|
||||
},
|
||||
{
|
||||
name: 'Right top to left bottom',
|
||||
value: '7',
|
||||
start: [1, 0],
|
||||
end: [0, 1]
|
||||
},
|
||||
{
|
||||
name: 'Right bottom to left top',
|
||||
value: '8',
|
||||
start: [1, 1],
|
||||
end: [0, 0]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -21,7 +21,8 @@ import {
|
||||
shapeListMap as shapeListMapZh,
|
||||
lineStyleMap as lineStyleMapZh,
|
||||
numberTypeList as numberTypeListZh,
|
||||
numberLevelList as numberLevelListZh
|
||||
numberLevelList as numberLevelListZh,
|
||||
linearGradientDirList as linearGradientDirListZh
|
||||
} from './zh'
|
||||
import {
|
||||
fontFamilyList as fontFamilyListEn,
|
||||
@@ -36,7 +37,8 @@ import {
|
||||
backgroundSizeList as backgroundSizeListEn,
|
||||
downTypeList as downTypeListEn,
|
||||
numberTypeList as numberTypeListEn,
|
||||
numberLevelList as numberLevelListEn
|
||||
numberLevelList as numberLevelListEn,
|
||||
linearGradientDirList as linearGradientDirListEn
|
||||
} from './en'
|
||||
|
||||
const fontFamilyList = {
|
||||
@@ -114,6 +116,11 @@ const numberLevelList = {
|
||||
en: numberLevelListEn
|
||||
}
|
||||
|
||||
const linearGradientDirList = {
|
||||
zh: linearGradientDirListZh,
|
||||
en: linearGradientDirListEn
|
||||
}
|
||||
|
||||
export {
|
||||
fontSizeList,
|
||||
lineHeightList,
|
||||
@@ -137,5 +144,6 @@ export {
|
||||
sidebarTriggerList,
|
||||
downTypeList,
|
||||
numberTypeList,
|
||||
numberLevelList
|
||||
numberLevelList,
|
||||
linearGradientDirList
|
||||
}
|
||||
|
||||
@@ -593,6 +593,18 @@ export const downTypeList = [
|
||||
type: 'txt',
|
||||
icon: 'iconTXT',
|
||||
desc: '纯文本文件'
|
||||
},
|
||||
{
|
||||
name: 'FreeMind',
|
||||
type: 'mm',
|
||||
icon: 'iconfreemind',
|
||||
desc: 'FreeMind软件格式'
|
||||
},
|
||||
{
|
||||
name: 'Excel',
|
||||
type: 'xlsx',
|
||||
icon: 'iconfile-excel',
|
||||
desc: 'Excel软件格式'
|
||||
}
|
||||
]
|
||||
|
||||
@@ -655,3 +667,55 @@ export const numberLevelList = [
|
||||
value: 0
|
||||
}
|
||||
]
|
||||
|
||||
// 背景渐变方向
|
||||
export const linearGradientDirList = [
|
||||
{
|
||||
name: '从左到右',
|
||||
value: '1',
|
||||
start: [0, 0],
|
||||
end: [1, 0]
|
||||
},
|
||||
{
|
||||
name: '从右到左',
|
||||
value: '2',
|
||||
start: [1, 0],
|
||||
end: [0, 0]
|
||||
},
|
||||
{
|
||||
name: '从上到下',
|
||||
value: '3',
|
||||
start: [0, 0],
|
||||
end: [0, 1]
|
||||
},
|
||||
{
|
||||
name: '从下到上',
|
||||
value: '4',
|
||||
start: [0, 1],
|
||||
end: [0, 0]
|
||||
},
|
||||
{
|
||||
name: '从左上到右下',
|
||||
value: '5',
|
||||
start: [0, 0],
|
||||
end: [1, 1]
|
||||
},
|
||||
{
|
||||
name: '从左下到右上',
|
||||
value: '6',
|
||||
start: [0, 1],
|
||||
end: [1, 0]
|
||||
},
|
||||
{
|
||||
name: '从右上到左下',
|
||||
value: '7',
|
||||
start: [1, 0],
|
||||
end: [0, 1]
|
||||
},
|
||||
{
|
||||
name: '从右下到左上',
|
||||
value: '8',
|
||||
start: [1, 1],
|
||||
end: [0, 0]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -157,8 +157,9 @@ export default {
|
||||
import: {
|
||||
title: 'Import',
|
||||
selectFile: 'Select file',
|
||||
supportFile: 'Support .smm、.json、.xmind、.xlsx、.md file',
|
||||
enableFileTip: 'Please select .smm、.json、.xmind、.xlsx、.md 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',
|
||||
@@ -238,7 +239,8 @@ export default {
|
||||
endColor: 'End',
|
||||
arrowDir: 'Arrow dir',
|
||||
arrowDirStart: 'Start',
|
||||
arrowDirEnd: 'End'
|
||||
arrowDirEnd: 'End',
|
||||
direction: 'Direction'
|
||||
},
|
||||
theme: {
|
||||
title: 'Theme',
|
||||
@@ -305,7 +307,8 @@ export default {
|
||||
yes: 'Yes',
|
||||
no: 'No',
|
||||
exportError: 'Export failed',
|
||||
dragTip: 'Release here to import the file'
|
||||
dragTip: 'Release here to import the file',
|
||||
deleteNodeImgTip: 'Are you sure to delete the node image?'
|
||||
},
|
||||
mouseAction: {
|
||||
tip1:
|
||||
|
||||
@@ -155,8 +155,9 @@ export default {
|
||||
import: {
|
||||
title: '导入',
|
||||
selectFile: '选取文件',
|
||||
supportFile: '支持.smm、.json、.xmind、.xlsx、.md文件',
|
||||
enableFileTip: '请选择.smm、.json、.xmind、.xlsx、.md文件',
|
||||
support: '支持',
|
||||
file: '文件',
|
||||
pleaseSelect: '请选择',
|
||||
maxFileNum: '最多只能选择一个文件',
|
||||
notSelectTip: '请选择要导入的文件',
|
||||
fileContentError: '文件内容有误',
|
||||
@@ -236,7 +237,8 @@ export default {
|
||||
endColor: '结束',
|
||||
arrowDir: '箭头位置',
|
||||
arrowDirStart: '头部',
|
||||
arrowDirEnd: '尾部'
|
||||
arrowDirEnd: '尾部',
|
||||
direction: '方向'
|
||||
},
|
||||
theme: {
|
||||
title: '主题',
|
||||
@@ -299,7 +301,8 @@ export default {
|
||||
yes: '是',
|
||||
no: '否',
|
||||
exportError: '导出失败',
|
||||
dragTip: '在此释放以导入该文件'
|
||||
dragTip: '在此释放以导入该文件',
|
||||
deleteNodeImgTip: '是否确认删除该节点图片?'
|
||||
},
|
||||
mouseAction: {
|
||||
tip1: '当前:左键拖动画布,右键框选节点',
|
||||
|
||||
@@ -79,6 +79,11 @@ import OuterFrame from 'simple-mind-map/src/plugins/OuterFrame.js'
|
||||
// import Notation from 'simple-mind-map-plugin-notation'
|
||||
// 编号插件,该插件为付费插件,详情请查看开发文档
|
||||
// import Numbers from 'simple-mind-map-plugin-numbers'
|
||||
// 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'
|
||||
@@ -418,6 +423,25 @@ export default {
|
||||
},
|
||||
expandBtnNumHandler: num => {
|
||||
return num >= 100 ? '…' : num
|
||||
},
|
||||
beforeDeleteNodeImg: node => {
|
||||
return new Promise(resolve => {
|
||||
this.$confirm(
|
||||
this.$t('edit.deleteNodeImgTip'),
|
||||
this.$t('edit.tip'),
|
||||
{
|
||||
confirmButtonText: this.$t('edit.yes'),
|
||||
cancelButtonText: this.$t('edit.no'),
|
||||
type: 'warning'
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
resolve(false)
|
||||
})
|
||||
.catch(() => {
|
||||
resolve(true)
|
||||
})
|
||||
})
|
||||
}
|
||||
// createNodePrefixContent: (node) => {
|
||||
// const el = document.createElement('div')
|
||||
@@ -544,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()
|
||||
})
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
element-loading-spinner="el-icon-loading"
|
||||
element-loading-background="rgba(0, 0, 0, 0.8)"
|
||||
:width="isMobile ? '90%' : '50%'"
|
||||
:top="isMobile? '20px' : '15vh'"
|
||||
:top="isMobile ? '20px' : '15vh'"
|
||||
>
|
||||
<div class="exportContainer" :class="{ isDark: isDark }">
|
||||
<div class="nameInputBox">
|
||||
@@ -98,12 +98,14 @@
|
||||
import { mapState, mapMutations } from 'vuex'
|
||||
import { downTypeList } from '@/config'
|
||||
import { isMobile } from 'simple-mind-map/src/utils/index'
|
||||
import MarkdownIt from 'markdown-it'
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
* @Date: 2021-06-24 22:53:54
|
||||
* @Desc: 导出
|
||||
*/
|
||||
let md = null
|
||||
export default {
|
||||
name: 'Export',
|
||||
data() {
|
||||
@@ -124,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() {
|
||||
@@ -203,6 +217,22 @@ export default {
|
||||
this.fileName,
|
||||
this.isTransparent
|
||||
)
|
||||
} else if (this.exportType === 'mm') {
|
||||
this.$bus.$emit('export', this.exportType, true, this.fileName, {
|
||||
transformNote: note => {
|
||||
if (!md) {
|
||||
md = new MarkdownIt()
|
||||
}
|
||||
return md.render(note)
|
||||
},
|
||||
transformImage: img => {
|
||||
if (/^https?:\/\//.test(img)) {
|
||||
return img
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
this.$bus.$emit('export', this.exportType, true, this.fileName)
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
<el-upload
|
||||
ref="upload"
|
||||
action="x"
|
||||
accept=".smm,.json,.xmind,.xlsx,.md"
|
||||
: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">
|
||||
@@ -40,9 +40,12 @@
|
||||
:show-close="false"
|
||||
>
|
||||
<el-radio-group v-model="selectCanvas" class="canvasList">
|
||||
<el-radio v-for="(item, index) in canvasList" :key="index" :label="index">{{
|
||||
item.title
|
||||
}}</el-radio>
|
||||
<el-radio
|
||||
v-for="(item, index) in canvasList"
|
||||
:key="index"
|
||||
:label="index"
|
||||
>{{ item.title }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button type="primary" @click="confirmSelect">{{
|
||||
@@ -56,9 +59,8 @@
|
||||
<script>
|
||||
import xmind from 'simple-mind-map/src/parse/xmind.js'
|
||||
import markdown from 'simple-mind-map/src/parse/markdown.js'
|
||||
import { fileToBuffer } from '@/utils'
|
||||
import { read, utils } from 'xlsx'
|
||||
import { mapMutations } from 'vuex'
|
||||
import { mapMutations, mapState } from 'vuex'
|
||||
import Vue from 'vue'
|
||||
|
||||
/**
|
||||
* @Author: 王林
|
||||
@@ -77,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) {
|
||||
@@ -101,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)$/.exec(fileURL)
|
||||
const macth = this.getRegexp().exec(fileURL)
|
||||
if (!macth) {
|
||||
return
|
||||
}
|
||||
@@ -124,6 +150,8 @@ export default {
|
||||
this.handleExcel(data)
|
||||
} else if (type === 'md') {
|
||||
this.handleMd(data)
|
||||
} else if (type === 'mm') {
|
||||
this.handleMm(data)
|
||||
}
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
@@ -132,9 +160,12 @@ export default {
|
||||
|
||||
// 文件选择
|
||||
onChange(file) {
|
||||
let reg = /\.(smm|xmind|json|xlsx|md)$/
|
||||
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)
|
||||
@@ -171,6 +202,8 @@ export default {
|
||||
this.handleExcel(file)
|
||||
} else if (/\.md$/.test(file.name)) {
|
||||
this.handleMd(file)
|
||||
} else if (/\.mm$/.test(file.name)) {
|
||||
this.handleMm(file)
|
||||
}
|
||||
this.cancel()
|
||||
this.setActiveSidebar(null)
|
||||
@@ -212,6 +245,36 @@ export default {
|
||||
}
|
||||
},
|
||||
|
||||
// 处理Freemind格式
|
||||
handleMm(file) {
|
||||
const fileReader = new FileReader()
|
||||
fileReader.readAsText(file.raw)
|
||||
fileReader.onload = async evt => {
|
||||
try {
|
||||
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) {
|
||||
console.log(error)
|
||||
this.$message.error(this.$t('import.fileParsingFailed'))
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// 显示xmind文件的多个画布选择弹窗
|
||||
showSelectXmindCanvasDialog(content) {
|
||||
this.canvasList = content
|
||||
@@ -230,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)
|
||||
@@ -296,7 +308,7 @@ export default {
|
||||
fileReader.readAsText(file.raw)
|
||||
fileReader.onload = async evt => {
|
||||
try {
|
||||
let data = await markdown.transformMarkdownTo(evt.target.result)
|
||||
let data = markdown.transformMarkdownTo(evt.target.result)
|
||||
this.$bus.$emit('setData', data)
|
||||
this.$message.success(this.$t('import.importSuccess'))
|
||||
} catch (error) {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
</el-tooltip>
|
||||
<div class="scaleInfo">
|
||||
<input
|
||||
ref="inputRef"
|
||||
type="text"
|
||||
v-model="scaleNum"
|
||||
@input="onScaleNumInput"
|
||||
@@ -55,13 +56,16 @@ export default {
|
||||
watch: {
|
||||
mindMap(val, oldVal) {
|
||||
if (val && !oldVal) {
|
||||
this.mindMap.on('scale', scale => {
|
||||
this.scaleNum = this.toPer(scale)
|
||||
})
|
||||
this.mindMap.on('scale', this.onScale)
|
||||
this.mindMap.on('draw_click', this.onDrawClick)
|
||||
this.scaleNum = this.toPer(this.mindMap.view.scale)
|
||||
}
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.mindMap.off('scale', this.onScale)
|
||||
this.mindMap.off('draw_click', this.onDrawClick)
|
||||
},
|
||||
methods: {
|
||||
// 转换成百分数
|
||||
toPer(scale) {
|
||||
@@ -98,6 +102,14 @@ export default {
|
||||
const cy = this.mindMap.height / 2
|
||||
this.mindMap.view.setScale(this.scaleNum / 100, cx, cy)
|
||||
}
|
||||
},
|
||||
|
||||
onScale(scale) {
|
||||
this.scaleNum = this.toPer(scale)
|
||||
},
|
||||
|
||||
onDrawClick() {
|
||||
if (this.$refs.inputRef) this.$refs.inputRef.blur()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -247,16 +247,16 @@
|
||||
<el-popover ref="popover4" placement="bottom" trigger="hover">
|
||||
<Color :color="style.fillColor" @change="changeFillColor"></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('style.gradientStyle') }}</span>
|
||||
<span class="name" style="margin-left: 20px;">{{
|
||||
$t('style.gradientStyle')
|
||||
}}</span>
|
||||
<el-checkbox
|
||||
v-model="style.gradientStyle"
|
||||
@change="update('gradientStyle')"
|
||||
></el-checkbox>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row" v-if="style.gradientStyle">
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('style.startColor') }}</span>
|
||||
<span
|
||||
@@ -282,6 +282,24 @@
|
||||
<Color :color="style.endColor" @change="changeEndColor"></Color>
|
||||
</el-popover>
|
||||
</div>
|
||||
<div class="rowItem">
|
||||
<span class="name">{{ $t('style.direction') }}</span>
|
||||
<el-select
|
||||
size="mini"
|
||||
style="width: 80px"
|
||||
v-model="style.linearGradientDir"
|
||||
placeholder=""
|
||||
@change="update('linearGradientDir')"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in linearGradientDirList"
|
||||
:key="item.value"
|
||||
:label="item.name"
|
||||
:value="item.value"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 形状 -->
|
||||
<div class="title">{{ $t('style.shape') }}</div>
|
||||
@@ -458,7 +476,8 @@ import {
|
||||
borderRadiusList,
|
||||
lineHeightList,
|
||||
shapeList,
|
||||
shapeListMap
|
||||
shapeListMap,
|
||||
linearGradientDirList
|
||||
} from '@/config'
|
||||
import { mapState } from 'vuex'
|
||||
|
||||
@@ -502,7 +521,8 @@ export default {
|
||||
lineMarkerDir: '',
|
||||
gradientStyle: false,
|
||||
startColor: '',
|
||||
endColor: ''
|
||||
endColor: '',
|
||||
linearGradientDir: ''
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -522,6 +542,11 @@ export default {
|
||||
},
|
||||
shapeListMap() {
|
||||
return shapeListMap[this.$i18n.locale] || shapeListMap.zh
|
||||
},
|
||||
linearGradientDirList() {
|
||||
return (
|
||||
linearGradientDirList[this.$i18n.locale] || linearGradientDirList.zh
|
||||
)
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -587,6 +612,24 @@ export default {
|
||||
].forEach(item => {
|
||||
this.style[item] = this.activeNodes[0].getStyle(item, false)
|
||||
})
|
||||
this.initLinearGradientDir()
|
||||
},
|
||||
|
||||
// 初始化渐变方向样式
|
||||
initLinearGradientDir() {
|
||||
const startDir = this.activeNodes[0].getStyle('startDir', false)
|
||||
const endDir = this.activeNodes[0].getStyle('endDir', false)
|
||||
const target = this.linearGradientDirList.find(item => {
|
||||
return (
|
||||
item.start[0] === startDir[0] &&
|
||||
item.start[1] === startDir[1] &&
|
||||
item.end[0] === endDir[0] &&
|
||||
item.end[1] === endDir[1]
|
||||
)
|
||||
})
|
||||
if (target) {
|
||||
this.style.linearGradientDir = target.value
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
@@ -595,9 +638,21 @@ export default {
|
||||
* @Desc: 修改样式
|
||||
*/
|
||||
update(prop) {
|
||||
this.activeNodes.forEach(node => {
|
||||
node.setStyle(prop, this.style[prop])
|
||||
})
|
||||
if (prop === 'linearGradientDir') {
|
||||
const target = this.linearGradientDirList.find(item => {
|
||||
return item.value === this.style.linearGradientDir
|
||||
})
|
||||
this.activeNodes.forEach(node => {
|
||||
node.setStyles({
|
||||
startDir: [...target.start],
|
||||
endDir: [...target.end]
|
||||
})
|
||||
})
|
||||
} else {
|
||||
this.activeNodes.forEach(node => {
|
||||
node.setStyle(prop, this.style[prop])
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user