mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2025-06-12 11:28:55 +00:00
多文件支持
This commit is contained in:
BIN
public/assets/Other/Contact.png
Normal file
BIN
public/assets/Other/Contact.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 51 KiB |
74
src/App.vue
74
src/App.vue
@ -5,7 +5,7 @@ import ProjectExplorer from './components/ProjectExplorer.vue';
|
|||||||
import { computed, ref, onMounted, onUnmounted } from "vue";
|
import { computed, ref, onMounted, onUnmounted } from "vue";
|
||||||
import { useFilesStore } from "@/stores/files";
|
import { useFilesStore } from "@/stores/files";
|
||||||
import Vue3DraggableResizable from 'vue3-draggable-resizable';
|
import Vue3DraggableResizable from 'vue3-draggable-resizable';
|
||||||
import {TabPaneName, TabsPaneContext} from "element-plus";
|
import { TabPaneName, TabsPaneContext } from "element-plus";
|
||||||
|
|
||||||
const filesStore = useFilesStore();
|
const filesStore = useFilesStore();
|
||||||
|
|
||||||
@ -21,12 +21,49 @@ const onResizing = (x, y, width, height) => {
|
|||||||
height.value = height;
|
height.value = height;
|
||||||
};
|
};
|
||||||
|
|
||||||
const onHandleInport = (file) => {
|
const handleExport = () => {
|
||||||
yysRef.value.importGroups(file);
|
const dataStr = JSON.stringify(filesStore.fileList, null, 2);
|
||||||
|
const blob = new Blob([dataStr], { type: 'application/json;charset=utf-8' });
|
||||||
|
const url = URL.createObjectURL(blob);
|
||||||
|
const link = document.createElement('a');
|
||||||
|
link.href = url;
|
||||||
|
link.download = 'files.json';
|
||||||
|
link.click();
|
||||||
|
URL.revokeObjectURL(url);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onHandleInport = (file) => {
|
||||||
|
const reader = new FileReader();
|
||||||
|
reader.onload = (e) => {
|
||||||
|
try {
|
||||||
|
const data = JSON.parse(e.target.result as string);
|
||||||
|
if (data[0].visible === true) {
|
||||||
|
// 新版本格式:直接替换 fileList
|
||||||
|
filesStore.$patch({ fileList: data });
|
||||||
|
} else {
|
||||||
|
// 旧版本格式:仅包含 groups 数组
|
||||||
|
const newFile = {
|
||||||
|
label: `File ${filesStore.fileList.length + 1}`,
|
||||||
|
name: String(filesStore.fileList.length + 1),
|
||||||
|
visible: true,
|
||||||
|
groups: data
|
||||||
|
};
|
||||||
|
filesStore.addFile(newFile);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to import file', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
reader.readAsText(file);
|
||||||
|
};
|
||||||
|
|
||||||
|
// const onHandleInport = (file) => {
|
||||||
|
//
|
||||||
|
// handleImport(file);
|
||||||
|
// };
|
||||||
|
|
||||||
const onHandleExport = () => {
|
const onHandleExport = () => {
|
||||||
yysRef.value.exportGroups();
|
handleExport();
|
||||||
};
|
};
|
||||||
|
|
||||||
const element = ref({
|
const element = ref({
|
||||||
@ -39,20 +76,18 @@ const element = ref({
|
|||||||
|
|
||||||
const handleFileSelected = (fileId) => {
|
const handleFileSelected = (fileId) => {
|
||||||
filesStore.setActiveFile(fileId);
|
filesStore.setActiveFile(fileId);
|
||||||
|
filesStore.setVisible(fileId, true);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleTabsEdit = (
|
const handleTabsEdit = (
|
||||||
targetName: TabPaneName | undefined,
|
targetName: String | undefined,
|
||||||
action: 'remove' | 'add'
|
action: 'remove' | 'add'
|
||||||
)=> {
|
) => {
|
||||||
const tabIndex = filesStore.fileList.findIndex(file => file.name === parseInt(name.toString()));
|
if (action === 'remove') {
|
||||||
if (tabIndex !== -1) {
|
filesStore.closeTab(targetName);
|
||||||
filesStore.fileList.splice(tabIndex, 1);
|
} else if (action === 'add') {
|
||||||
if (filesStore.fileList.length > 0) {
|
const newFileName = `File ${filesStore.fileList.length + 1}`;
|
||||||
filesStore.setActiveFile(filesStore.fileList[0].name);
|
filesStore.addFile({ label: newFileName, name: newFileName });
|
||||||
} else {
|
|
||||||
filesStore.setActiveFile(-1); // 或者其他适当的值表示没有活动文件
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -67,6 +102,11 @@ onUnmounted(() => {
|
|||||||
windowHeight.value = window.innerHeight;
|
windowHeight.value = window.innerHeight;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const activeFileGroups = computed(() => {
|
||||||
|
const activeFile = filesStore.fileList.find(file => file.name === filesStore.activeFile);
|
||||||
|
return activeFile ? activeFile.groups : [];
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
@ -77,7 +117,7 @@ onUnmounted(() => {
|
|||||||
<div class="main-content">
|
<div class="main-content">
|
||||||
<!-- 侧边栏 -->
|
<!-- 侧边栏 -->
|
||||||
<aside class="sidebar">
|
<aside class="sidebar">
|
||||||
<ProjectExplorer :files="filesStore.fileList" @file-selected="handleFileSelected" />
|
<ProjectExplorer :allFiles="filesStore.fileList" @file-selected="handleFileSelected" />
|
||||||
</aside>
|
</aside>
|
||||||
|
|
||||||
<!-- 工作区 -->
|
<!-- 工作区 -->
|
||||||
@ -91,12 +131,12 @@ onUnmounted(() => {
|
|||||||
@edit="handleTabsEdit"
|
@edit="handleTabsEdit"
|
||||||
>
|
>
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-for="(file, index) in filesStore.fileList"
|
v-for="(file, index) in filesStore.visibleFiles"
|
||||||
:key="index"
|
:key="index"
|
||||||
:label="file.label"
|
:label="file.label"
|
||||||
:name="file.name.toString()"
|
:name="file.name.toString()"
|
||||||
>
|
>
|
||||||
<Yys ref="yysRef" />
|
<Yys :groups="activeFileGroups" ref="yysRef" />
|
||||||
</el-tab-pane>
|
</el-tab-pane>
|
||||||
</el-tabs>
|
</el-tabs>
|
||||||
</main>
|
</main>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="project-explorer">
|
<div class="project-explorer">
|
||||||
<el-tree
|
<el-tree
|
||||||
:data="files"
|
:data="allFiles"
|
||||||
:props="defaultProps"
|
:props="defaultProps"
|
||||||
@node-click="handleNodeClick"
|
@node-click="handleNodeClick"
|
||||||
/>
|
/>
|
||||||
@ -9,10 +9,10 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { defineProps, defineEmits } from 'vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
files: {
|
allFiles: {
|
||||||
type: Array,
|
type: Array,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
|
@ -130,6 +130,7 @@ import YuhunSelect from "@/components/YuhunSelect.vue";
|
|||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
// import YuhunSelect from "./YuhunSelect.vue";
|
// import YuhunSelect from "./YuhunSelect.vue";
|
||||||
|
|
||||||
|
|
||||||
// 获取当前的 i18n 实例
|
// 获取当前的 i18n 实例
|
||||||
const {t} = useI18n()
|
const {t} = useI18n()
|
||||||
|
|
||||||
@ -339,7 +340,7 @@ const cancel = () => {
|
|||||||
|
|
||||||
const confirm = () => {
|
const confirm = () => {
|
||||||
shikigami.value.edit = true
|
shikigami.value.edit = true
|
||||||
emit('updateProperty', JSON.parse(JSON.stringify(shikigami.value)))
|
emit('updateProperty', shikigami.value);
|
||||||
resetData()
|
resetData()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,14 +8,37 @@
|
|||||||
t('setWatermark')
|
t('setWatermark')
|
||||||
}}
|
}}
|
||||||
</el-button>
|
</el-button>
|
||||||
|
<!-- 新增的按钮 -->
|
||||||
|
<el-button type="info" @click="showUpdateLog">更新日志</el-button>
|
||||||
|
<el-button type="warning" @click="showFeedbackForm">问题反馈</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- 更新日志对话框 -->
|
||||||
|
<el-dialog v-model="state.showUpdateLogDialog" title="更新日志" width="60%">
|
||||||
|
<ul>
|
||||||
|
<li v-for="(log, index) in updateLogs" :key="index">
|
||||||
|
<strong>版本 {{ log.version }} - {{ log.date }}</strong>
|
||||||
|
<ul>
|
||||||
|
<li v-for="(change, idx) in log.changes" :key="idx">{{ change }}</li>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
|
<!-- 更新日志对话框 -->
|
||||||
|
<el-dialog v-model="state.showFeedbackFormDialog" title="更新日志" width="60%">
|
||||||
|
<span style="font-size: 24px;">备注阴阳师</span>
|
||||||
|
<br/>
|
||||||
|
<img src="/assets/Other/Contact.png"
|
||||||
|
style="cursor: pointer; vertical-align: bottom; width: 200px; height: auto;"/>
|
||||||
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 预览弹窗 -->
|
<!-- 预览弹窗 -->
|
||||||
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" height="80%" :before-close="handleClose">
|
<el-dialog id="preview-container" v-model="state.previewVisible" width="80%" height="80%"
|
||||||
|
:before-close="handleClose">
|
||||||
<div style="max-height: 500px; overflow-y: auto;">
|
<div style="max-height: 500px; overflow-y: auto;">
|
||||||
<img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; display: block;"/>
|
<img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; display: block;"/>
|
||||||
</div>
|
</div>
|
||||||
<!-- <img v-if="state.previewImage" :src="state.previewImage" alt="Preview" style="width: 100%; height: auto;" />-->
|
|
||||||
<span slot="footer" class="dialog-footer">
|
<span slot="footer" class="dialog-footer">
|
||||||
<el-button @click="state.previewVisible = false">取 消</el-button>
|
<el-button @click="state.previewVisible = false">取 消</el-button>
|
||||||
<el-button type="primary" @click="downloadImage">下 载</el-button>
|
<el-button type="primary" @click="downloadImage">下 载</el-button>
|
||||||
@ -62,15 +85,46 @@ import {useI18n} from 'vue-i18n';
|
|||||||
|
|
||||||
// 获取当前的 i18n 实例
|
// 获取当前的 i18n 实例
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
const emit = defineEmits(['handleExport', 'handleImport'])
|
const emit = defineEmits(['handleExport', 'handleImport']);
|
||||||
|
|
||||||
// 定义响应式数据
|
// 定义响应式数据
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
previewImage: null, // 用于存储预览图像的数据URL
|
previewImage: null, // 用于存储预览图像的数据URL
|
||||||
previewVisible: false, // 控制预览弹窗的显示状态
|
previewVisible: false, // 控制预览弹窗的显示状态
|
||||||
showWatermarkDialog: false, // 控制水印设置弹窗的显示状态
|
showWatermarkDialog: false, // 控制水印设置弹窗的显示状态,
|
||||||
|
showUpdateLogDialog: false, // 控制更新日志对话框的显示状态
|
||||||
|
showFeedbackFormDialog: false, // 控制反馈表单对话框的显示状态
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 版本记录数据
|
||||||
|
const updateLogs = [
|
||||||
|
{
|
||||||
|
version: '2.0.0',
|
||||||
|
date: '2025-03-16',
|
||||||
|
changes: [
|
||||||
|
'修复了相同式神不能正确设置属性的问题',
|
||||||
|
'支持了多文件编辑',
|
||||||
|
'PS:当前导出截图宽度无法'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
version: '1.0.0',
|
||||||
|
date: '2025-03-09',
|
||||||
|
changes: [
|
||||||
|
'首次发布'
|
||||||
|
]
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
const showUpdateLog = () => {
|
||||||
|
state.showUpdateLogDialog = !state.showUpdateLogDialog;
|
||||||
|
};
|
||||||
|
|
||||||
|
const showFeedbackForm = () => {
|
||||||
|
state.showFeedbackFormDialog = !state.showFeedbackFormDialog;
|
||||||
|
};
|
||||||
|
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
emit('handleExport');
|
emit('handleExport');
|
||||||
};
|
};
|
||||||
@ -86,7 +140,6 @@ const handleImport = () => {
|
|||||||
input.click();
|
input.click();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const watermark = reactive({
|
const watermark = reactive({
|
||||||
text: '示例水印',
|
text: '示例水印',
|
||||||
fontSize: 30,
|
fontSize: 30,
|
||||||
@ -150,7 +203,6 @@ function calculateVisualHeight(selector) {
|
|||||||
return rows.reduce((sum, row) => sum + row.maxHeight, 0);
|
return rows.reduce((sum, row) => sum + row.maxHeight, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const ignoreElements = (element) => {
|
const ignoreElements = (element) => {
|
||||||
return element.classList.contains('ql-toolbar') || element.classList.contains('el-tabs__header');
|
return element.classList.contains('ql-toolbar') || element.classList.contains('el-tabs__header');
|
||||||
};
|
};
|
||||||
@ -248,6 +300,7 @@ const prepareCapture = async () => {
|
|||||||
document.head.removeChild(style);
|
document.head.removeChild(style);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadImage = () => {
|
const downloadImage = () => {
|
||||||
if (state.previewImage) {
|
if (state.previewImage) {
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
@ -272,7 +325,6 @@ const handleClose = (done) => {
|
|||||||
right: 0;
|
right: 0;
|
||||||
height: 48px;
|
height: 48px;
|
||||||
background: #f8f8f8;
|
background: #f8f8f8;
|
||||||
//border-bottom: 1px solid #eee; display: flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
<draggable :list="state.groups" item-key="group" style="display: flex; flex-direction: column; width: 100%;"
|
<draggable :list="groups" item-key="group" style="display: flex; flex-direction: column; width: 100%;"
|
||||||
handle=".drag-handle">
|
handle=".drag-handle">
|
||||||
|
|
||||||
|
|
||||||
@ -126,7 +126,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup>
|
<script setup lang="ts">
|
||||||
import {ref, reactive, toRefs} from 'vue';
|
import {ref, reactive, toRefs} from 'vue';
|
||||||
import draggable from 'vuedraggable';
|
import draggable from 'vuedraggable';
|
||||||
import ShikigamiSelect from './ShikigamiSelect.vue';
|
import ShikigamiSelect from './ShikigamiSelect.vue';
|
||||||
@ -139,35 +139,15 @@ import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
|||||||
import shikigamiData from '../data/Shikigami.json';
|
import shikigamiData from '../data/Shikigami.json';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
|
||||||
|
const props = defineProps<{
|
||||||
|
groups: any[];
|
||||||
|
}>();
|
||||||
|
|
||||||
const dialogTableVisible = ref(false)
|
const dialogTableVisible = ref(false)
|
||||||
// 定义响应式数据
|
// 定义响应式数据
|
||||||
const state = reactive({
|
const state = reactive({
|
||||||
showSelectShikigami: false,
|
showSelectShikigami: false,
|
||||||
showProperty: false,
|
showProperty: false,
|
||||||
groups: [
|
|
||||||
{
|
|
||||||
shortDescription: '',
|
|
||||||
groupInfo: [{}, {}, {}, {}, {}],
|
|
||||||
details: ''
|
|
||||||
},
|
|
||||||
{
|
|
||||||
shortDescription: '',
|
|
||||||
groupInfo: [{}, {}, {}, {}, {}],
|
|
||||||
details: ''
|
|
||||||
},{
|
|
||||||
shortDescription: '',
|
|
||||||
groupInfo: [{}, {}, {}, {}, {}],
|
|
||||||
details: ''
|
|
||||||
},{
|
|
||||||
shortDescription: '',
|
|
||||||
groupInfo: [{}, {}, {}, {}, {}],
|
|
||||||
details: ''
|
|
||||||
},{
|
|
||||||
shortDescription: '',
|
|
||||||
groupInfo: [{}, {}, {}, {}, {}],
|
|
||||||
details: ''
|
|
||||||
},
|
|
||||||
],
|
|
||||||
groupIndex: 0,
|
groupIndex: 0,
|
||||||
positionIndex: 0,
|
positionIndex: 0,
|
||||||
currentShikigami: {},
|
currentShikigami: {},
|
||||||
@ -187,9 +167,9 @@ const copy = (str) => {
|
|||||||
|
|
||||||
const paste = (groupIndex, type) => {
|
const paste = (groupIndex, type) => {
|
||||||
if ('shortDescription' == type)
|
if ('shortDescription' == type)
|
||||||
state.groups[groupIndex].shortDescription = clipboard.value
|
props.groups[groupIndex].shortDescription = clipboard.value
|
||||||
else if ('details' == type)
|
else if ('details' == type)
|
||||||
state.groups[groupIndex].details = clipboard.value
|
props.groups[groupIndex].details = clipboard.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义工具栏选项
|
// 定义工具栏选项
|
||||||
@ -223,23 +203,23 @@ const editShikigami = (groupIndex, positionIndex) => {
|
|||||||
state.showSelectShikigami = true;
|
state.showSelectShikigami = true;
|
||||||
state.groupIndex = groupIndex;
|
state.groupIndex = groupIndex;
|
||||||
state.positionIndex = positionIndex;
|
state.positionIndex = positionIndex;
|
||||||
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
|
state.currentShikigami = props.groups[groupIndex].groupInfo[positionIndex];
|
||||||
};
|
};
|
||||||
|
|
||||||
const updateShikigami = (shikigami) => {
|
const updateShikigami = (shikigami) => {
|
||||||
console.log("parent====> ", shikigami);
|
console.log("parent====> ", shikigami);
|
||||||
state.showSelectShikigami = false;
|
state.showSelectShikigami = false;
|
||||||
|
|
||||||
const oldProperties = state.groups[state.groupIndex].groupInfo[state.positionIndex].properties;
|
const oldProperties = props.groups[state.groupIndex].groupInfo[state.positionIndex].properties;
|
||||||
state.groups[state.groupIndex].groupInfo[state.positionIndex] = _.cloneDeep(shikigami);
|
props.groups[state.groupIndex].groupInfo[state.positionIndex] = _.cloneDeep(shikigami);
|
||||||
state.groups[state.groupIndex].groupInfo[state.positionIndex].properties = oldProperties;
|
props.groups[state.groupIndex].groupInfo[state.positionIndex].properties = oldProperties;
|
||||||
};
|
};
|
||||||
|
|
||||||
const editProperty = (groupIndex, positionIndex) => {
|
const editProperty = (groupIndex, positionIndex) => {
|
||||||
state.showProperty = true;
|
state.showProperty = true;
|
||||||
state.groupIndex = groupIndex;
|
state.groupIndex = groupIndex;
|
||||||
state.positionIndex = positionIndex;
|
state.positionIndex = positionIndex;
|
||||||
state.currentShikigami = state.groups[groupIndex].groupInfo[positionIndex];
|
state.currentShikigami = props.groups[groupIndex].groupInfo[positionIndex];
|
||||||
};
|
};
|
||||||
|
|
||||||
const closeProperty = () => {
|
const closeProperty = () => {
|
||||||
@ -250,19 +230,19 @@ const closeProperty = () => {
|
|||||||
const updateProperty = (property) => {
|
const updateProperty = (property) => {
|
||||||
state.showProperty = false;
|
state.showProperty = false;
|
||||||
state.currentShikigami = {};
|
state.currentShikigami = {};
|
||||||
state.groups[state.groupIndex].groupInfo[state.positionIndex].properties = _.cloneDeep(property);
|
props.groups[state.groupIndex].groupInfo[state.positionIndex].properties = _.cloneDeep(property);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeGroupElement = (groupIndex, positionIndex) => {
|
const removeGroupElement = (groupIndex, positionIndex) => {
|
||||||
state.groups[groupIndex].groupInfo.splice(positionIndex, 1);
|
props.groups[groupIndex].groupInfo.splice(positionIndex, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeGroup = (groupIndex) => {
|
const removeGroup = (groupIndex) => {
|
||||||
state.groups.splice(groupIndex, 1);
|
props.groups.splice(groupIndex, 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
const addGroup = () => {
|
const addGroup = () => {
|
||||||
state.groups.push({
|
props.groups.push({
|
||||||
shortDescription: '',
|
shortDescription: '',
|
||||||
groupInfo: [{}, {}, {}, {}, {}],
|
groupInfo: [{}, {}, {}, {}, {}],
|
||||||
details: ''
|
details: ''
|
||||||
@ -270,12 +250,12 @@ const addGroup = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const addGroupElement = (groupIndex) => {
|
const addGroupElement = (groupIndex) => {
|
||||||
state.groups[groupIndex].groupInfo.push({});
|
props.groups[groupIndex].groupInfo.push({});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
const exportGroups = () => {
|
const exportGroups = () => {
|
||||||
const dataStr = JSON.stringify(state.groups, null, 2);
|
const dataStr = JSON.stringify(props.groups, null, 2);
|
||||||
const blob = new Blob([dataStr], {type: 'application/json'});
|
const blob = new Blob([dataStr], {type: 'application/json'});
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
@ -326,7 +306,7 @@ const importGroups = (file) => {
|
|||||||
reader.onload = (e) => {
|
reader.onload = (e) => {
|
||||||
try {
|
try {
|
||||||
const importedData = JSON.parse(e.target.result);
|
const importedData = JSON.parse(e.target.result);
|
||||||
state.groups = importedData;
|
props.groups = importedData;
|
||||||
ElMessage.success('导入成功');
|
ElMessage.success('导入成功');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
ElMessage.error('文件格式错误');
|
ElMessage.error('文件格式错误');
|
||||||
|
@ -1,16 +1,69 @@
|
|||||||
import { defineStore } from 'pinia';
|
import {defineStore} from 'pinia';
|
||||||
|
|
||||||
export const useFilesStore = defineStore('files', {
|
export const useFilesStore = defineStore('files', {
|
||||||
state: () => ({
|
state: () => ({
|
||||||
fileList: [{ label: 'File 1', name: 1 },{ label: 'File 2', name: 2 }],
|
fileList: [
|
||||||
activeFile: 1,
|
{
|
||||||
|
label: 'File 1',
|
||||||
|
name: "1",
|
||||||
|
visible: true,
|
||||||
|
groups: [
|
||||||
|
{
|
||||||
|
shortDescription: '',
|
||||||
|
groupInfo: [{}, {}, {}, {}, {}],
|
||||||
|
details: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
shortDescription: '',
|
||||||
|
groupInfo: [{}, {}, {}, {}, {}],
|
||||||
|
details: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
label: 'File 2',
|
||||||
|
name: "2",
|
||||||
|
visible: true,
|
||||||
|
groups:[
|
||||||
|
{
|
||||||
|
shortDescription: '',
|
||||||
|
groupInfo: [{}, {}, {}, {}, {}],
|
||||||
|
details: ''
|
||||||
|
},
|
||||||
|
{
|
||||||
|
shortDescription: '',
|
||||||
|
groupInfo: [{}, {}, {}, {}, {}],
|
||||||
|
details: ''
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}],
|
||||||
|
activeFile: "1",
|
||||||
}),
|
}),
|
||||||
|
getters: {
|
||||||
|
visibleFiles: (state) => state.fileList.filter(file => file.visible),
|
||||||
|
},
|
||||||
actions: {
|
actions: {
|
||||||
addFile(file: { label: string; name: number }) {
|
addFile(file: { label: string; name: number }) {
|
||||||
this.fileList.push(file);
|
this.fileList.push({...file, visible: true});
|
||||||
|
this.activeFile = file.name;
|
||||||
},
|
},
|
||||||
setActiveFile(fileId: number) {
|
setActiveFile(fileId: number) {
|
||||||
this.activeFile = fileId;
|
this.activeFile = fileId;
|
||||||
},
|
},
|
||||||
|
setVisible(fileId: number, visibility: boolean) {
|
||||||
|
const file = this.fileList.find(file => file.name === fileId);
|
||||||
|
if (file) {
|
||||||
|
file.visible = visibility;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
closeTab(fileName: String) {
|
||||||
|
const file = this.fileList.find(file => file.name === fileName);
|
||||||
|
if (file) {
|
||||||
|
file.visible = false;
|
||||||
|
if (this.activeFile === fileName) {
|
||||||
|
const nextVisibleFile = this.visibleFiles[0];
|
||||||
|
this.activeFile = nextVisibleFile ? nextVisibleFile.name : -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
Reference in New Issue
Block a user