mirror of
https://github.com/Powerful-517/yys-editor.git
synced 2025-07-08 05:11:52 +00:00
@ -6,11 +6,19 @@
|
|||||||
:before-close="cancel"
|
:before-close="cancel"
|
||||||
>
|
>
|
||||||
<span>当前选择式神:{{ current.name }}</span>
|
<span>当前选择式神:{{ current.name }}</span>
|
||||||
|
<div style="display: flex; align-items: center;">
|
||||||
|
<el-input
|
||||||
|
placeholder="请输入内容"
|
||||||
|
v-model="searchText"
|
||||||
|
style="width: 200px; margin-right: 10px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<el-tabs
|
<el-tabs
|
||||||
v-model="activeName"
|
v-model="activeName"
|
||||||
type="card"
|
type="card"
|
||||||
class="demo-tabs"
|
class="demo-tabs"
|
||||||
@tab-click="handleClick"
|
@tab-click="handleClick"
|
||||||
|
editable
|
||||||
>
|
>
|
||||||
<el-tab-pane
|
<el-tab-pane
|
||||||
v-for="(rarity, index) in rarityLevels"
|
v-for="(rarity, index) in rarityLevels"
|
||||||
@ -20,7 +28,7 @@
|
|||||||
>
|
>
|
||||||
<div style="max-height: 600px; overflow-y: auto;">
|
<div style="max-height: 600px; overflow-y: auto;">
|
||||||
<el-space wrap size="large">
|
<el-space wrap size="large">
|
||||||
<div v-for="i in filterShikigamiByRarity(rarity.name)" :key="i.name">
|
<div v-for="i in filterShikigamiByRarityAndSearch(rarity.name,searchText)" :key="i.name">
|
||||||
<el-button
|
<el-button
|
||||||
style="width: 100px; height: 100px;"
|
style="width: 100px; height: 100px;"
|
||||||
@click.stop="confirm(i)"
|
@click.stop="confirm(i)"
|
||||||
@ -59,6 +67,7 @@ const props = defineProps({
|
|||||||
|
|
||||||
const emit = defineEmits(['closeSelectShikigami', 'updateShikigami'])
|
const emit = defineEmits(['closeSelectShikigami', 'updateShikigami'])
|
||||||
|
|
||||||
|
const searchText = ref('') // 新增搜索文本
|
||||||
const activeName = ref('ALL')
|
const activeName = ref('ALL')
|
||||||
let current = ref({name:''})
|
let current = ref({name:''})
|
||||||
const show = ref(false)
|
const show = ref(false)
|
||||||
@ -96,13 +105,25 @@ const cancel = () => {
|
|||||||
|
|
||||||
const confirm = (shikigami: Shikigami) => {
|
const confirm = (shikigami: Shikigami) => {
|
||||||
emit('updateShikigami', shikigami)
|
emit('updateShikigami', shikigami)
|
||||||
|
searchText.value=''
|
||||||
|
activeName.value='ALL'
|
||||||
// cancel()
|
// cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
const filterShikigamiByRarity = (rarity: string) => {
|
|
||||||
if (rarity.toLowerCase() === 'all') return shikigamiData
|
// 修改后的过滤函数
|
||||||
return shikigamiData.filter(item =>
|
const filterShikigamiByRarityAndSearch = (rarity: string, search: string) => {
|
||||||
item.rarity.toLowerCase() === rarity.toLowerCase()
|
let filteredList = shikigamiData;
|
||||||
)
|
if (rarity.toLowerCase() !== 'all') {
|
||||||
|
filteredList = filteredList.filter(item =>
|
||||||
|
item.rarity.toLowerCase() === rarity.toLowerCase()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (search.trim() !== '') {
|
||||||
|
return filteredList.filter(item =>
|
||||||
|
item.name.toLowerCase().includes(search.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return filteredList;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
@ -4,13 +4,10 @@
|
|||||||
<el-button icon="Upload" type="primary" @click="handleImport">{{ t('import') }}</el-button>
|
<el-button icon="Upload" type="primary" @click="handleImport">{{ t('import') }}</el-button>
|
||||||
<el-button icon="Download" type="primary" @click="handleExport">{{ t('export') }}</el-button>
|
<el-button icon="Download" type="primary" @click="handleExport">{{ t('export') }}</el-button>
|
||||||
<el-button icon="Share" type="primary" @click="prepareCapture">{{ t('prepareCapture') }}</el-button>
|
<el-button icon="Share" type="primary" @click="prepareCapture">{{ t('prepareCapture') }}</el-button>
|
||||||
<el-button icon="Setting" type="primary" @click="state.showWatermarkDialog = true">{{
|
<el-button icon="Setting" type="primary" @click="state.showWatermarkDialog = true">{{ t('setWatermark') }}</el-button>
|
||||||
t('setWatermark')
|
<el-button type="info" @click="loadExample">{{ t('loadExample') }}</el-button>
|
||||||
}}
|
<el-button type="info" @click="showUpdateLog">{{ t('updateLog') }}</el-button>
|
||||||
</el-button>
|
<el-button type="warning" @click="showFeedbackForm">{{ t('feedback') }}</el-button>
|
||||||
<!-- 新增的按钮 -->
|
|
||||||
<el-button type="info" @click="showUpdateLog">更新日志</el-button>
|
|
||||||
<el-button type="warning" @click="showFeedbackForm">问题反馈</el-button>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- 更新日志对话框 -->
|
<!-- 更新日志对话框 -->
|
||||||
@ -25,7 +22,7 @@
|
|||||||
</ul>
|
</ul>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
|
|
||||||
<!-- 更新日志对话框 -->
|
<!-- 问题反馈对话框 -->
|
||||||
<el-dialog v-model="state.showFeedbackFormDialog" title="更新日志" width="60%">
|
<el-dialog v-model="state.showFeedbackFormDialog" title="更新日志" width="60%">
|
||||||
<span style="font-size: 24px;">备注阴阳师</span>
|
<span style="font-size: 24px;">备注阴阳师</span>
|
||||||
<br/>
|
<br/>
|
||||||
@ -79,13 +76,17 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, reactive} from 'vue';
|
import {ref, reactive, onMounted} from 'vue';
|
||||||
import html2canvas from "html2canvas";
|
import html2canvas from "html2canvas";
|
||||||
import {useI18n} from 'vue-i18n';
|
import {useI18n} from 'vue-i18n';
|
||||||
import updateLogs from "../data/updateLog.json"
|
import updateLogs from "../data/updateLog.json"
|
||||||
|
import filesStoreExample from "../data/filesStoreExample.json"
|
||||||
import {useFilesStore} from "@/ts/files";
|
import {useFilesStore} from "@/ts/files";
|
||||||
|
import {ElMessageBox} from "element-plus";
|
||||||
|
import {useGlobalMessage} from "@/ts/useGlobalMessage";
|
||||||
|
|
||||||
const filesStore = useFilesStore();
|
const filesStore = useFilesStore();
|
||||||
|
const { showMessage } = useGlobalMessage();
|
||||||
|
|
||||||
// 获取当前的 i18n 实例
|
// 获取当前的 i18n 实例
|
||||||
const {t} = useI18n();
|
const {t} = useI18n();
|
||||||
@ -99,18 +100,47 @@ const state = reactive({
|
|||||||
showFeedbackFormDialog: false, // 控制反馈表单对话框的显示状态
|
showFeedbackFormDialog: false, // 控制反馈表单对话框的显示状态
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const loadExample = () => {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'加载样例会覆盖当前数据,是否覆盖?',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '覆盖',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
filesStore.$patch({fileList: filesStoreExample});
|
||||||
|
showMessage('success', '数据已恢复');
|
||||||
|
}).catch(() => {
|
||||||
|
showMessage('info', '选择了不恢复旧数据');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const CURRENT_APP_VERSION = updateLogs[0].version;
|
||||||
const showUpdateLog = () => {
|
const showUpdateLog = () => {
|
||||||
state.showUpdateLogDialog = !state.showUpdateLogDialog;
|
state.showUpdateLogDialog = !state.showUpdateLogDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
const lastVersion = localStorage.getItem('appVersion');
|
||||||
|
|
||||||
|
if (lastVersion !== CURRENT_APP_VERSION) {
|
||||||
|
// 如果版本号不同,则显示更新日志对话框
|
||||||
|
state.showUpdateLogDialog = true;
|
||||||
|
// 更新本地存储中的版本号为当前版本
|
||||||
|
localStorage.setItem('appVersion', CURRENT_APP_VERSION);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
const showFeedbackForm = () => {
|
const showFeedbackForm = () => {
|
||||||
state.showFeedbackFormDialog = !state.showFeedbackFormDialog;
|
state.showFeedbackFormDialog = !state.showFeedbackFormDialog;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleExport = () => {
|
const handleExport = () => {
|
||||||
const dataStr = JSON.stringify(filesStore.fileList, null, 2);
|
const dataStr = JSON.stringify(filesStore.fileList, null, 2);
|
||||||
const blob = new Blob([dataStr], { type: 'application/json;charset=utf-8' });
|
const blob = new Blob([dataStr], {type: 'application/json;charset=utf-8'});
|
||||||
const url = URL.createObjectURL(blob);
|
const url = URL.createObjectURL(blob);
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a');
|
||||||
link.href = url;
|
link.href = url;
|
||||||
@ -132,8 +162,8 @@ const handleImport = () => {
|
|||||||
const data = JSON.parse(e.target.result as string);
|
const data = JSON.parse(e.target.result as string);
|
||||||
if (data[0].visible === true) {
|
if (data[0].visible === true) {
|
||||||
// 新版本格式:直接替换 fileList
|
// 新版本格式:直接替换 fileList
|
||||||
filesStore.$patch({ fileList: data });
|
filesStore.$patch({fileList: data});
|
||||||
} else {
|
} else {
|
||||||
// 旧版本格式:仅包含 groups 数组
|
// 旧版本格式:仅包含 groups 数组
|
||||||
const newFile = {
|
const newFile = {
|
||||||
label: `File ${filesStore.fileList.length + 1}`,
|
label: `File ${filesStore.fileList.length + 1}`,
|
||||||
@ -154,18 +184,27 @@ const handleImport = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const watermark = reactive({
|
const watermark = reactive({
|
||||||
text: '示例水印',
|
text: localStorage.getItem('watermark.text') || '示例水印',
|
||||||
fontSize: 30,
|
fontSize: Number(localStorage.getItem('watermark.fontSize')) || 30,
|
||||||
color: 'rgba(184, 184, 184, 0.3)',
|
color: localStorage.getItem('watermark.color') || 'rgba(184, 184, 184, 0.3)',
|
||||||
angle: -20,
|
angle: Number(localStorage.getItem('watermark.angle')) || -20,
|
||||||
rows: 1, // 新增行数
|
rows: Number(localStorage.getItem('watermark.rows')) || 1,
|
||||||
cols: 1 // 新增列数
|
cols: Number(localStorage.getItem('watermark.cols')) || 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const applyWatermarkSettings = () => {
|
const applyWatermarkSettings = () => {
|
||||||
|
// 保存水印设置到 localStorage
|
||||||
|
localStorage.setItem('watermark.text', watermark.text);
|
||||||
|
localStorage.setItem('watermark.fontSize', String(watermark.fontSize));
|
||||||
|
localStorage.setItem('watermark.color', watermark.color);
|
||||||
|
localStorage.setItem('watermark.angle', String(watermark.angle));
|
||||||
|
localStorage.setItem('watermark.rows', String(watermark.rows));
|
||||||
|
localStorage.setItem('watermark.cols', String(watermark.cols));
|
||||||
|
|
||||||
state.showWatermarkDialog = false;
|
state.showWatermarkDialog = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// 计算视觉总高度
|
// 计算视觉总高度
|
||||||
function calculateVisualHeight(selector) {
|
function calculateVisualHeight(selector) {
|
||||||
// 1. 获取所有目标元素
|
// 1. 获取所有目标元素
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
|
|
||||||
<draggable :list="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">
|
||||||
|
|
||||||
|
|
||||||
<template class="group" #item="{ element: group, index: groupIndex }">
|
<template class="group" #item="{ element: group, index: groupIndex }">
|
||||||
<el-row :span="24">
|
<el-row :span="24">
|
||||||
<div class="group-item">
|
<div class="group-item">
|
||||||
@ -33,23 +31,23 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="opt-right">
|
<div class="opt-right">
|
||||||
<el-button class="drag-handle" type="primary" icon="Rank" circle></el-button>
|
<el-button class="drag-handle" type="primary" icon="Rank" circle></el-button>
|
||||||
<el-button type="primary" icon="Plus" circle @click="addGroup"></el-button>
|
<el-button type="primary" @click="addGroup">{{t('AddGroup')}}</el-button>
|
||||||
|
<el-button type="primary" @click="addGroupElement(groupIndex)">{{t('AddShikigami')}}</el-button>
|
||||||
<el-button type="danger" icon="Delete" circle @click="removeGroup(groupIndex)"></el-button>
|
<el-button type="danger" icon="Delete" circle @click="removeGroup(groupIndex)"></el-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<QuillEditor v-model:content="group.shortDescription" contentType="html" theme="snow"
|
<QuillEditor ref="shortDescriptionEditor" v-model:content="group.shortDescription" contentType="html" theme="snow" :toolbar="toolbarOptions"/>
|
||||||
:toolbar="toolbarOptions"/>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="group-body">
|
<div class="group-body">
|
||||||
<draggable :list="group.groupInfo" item-key="name" class="body-content">
|
<draggable :list="group.groupInfo" item-key="name" class="body-content">
|
||||||
<template #item="{element : position, index:positionIndex}">
|
<template #item="{element : position, index:positionIndex}">
|
||||||
<div>
|
<div>
|
||||||
<el-col>
|
<el-col>
|
||||||
<el-card class="group-card" shadow="never">
|
<el-card class="group-card" shadow="never">
|
||||||
<div class="opt-btn" data-html2canvas-ignore="true">
|
<div class="opt-btn" data-html2canvas-ignore="true">
|
||||||
<!-- Add delete button here -->
|
<!-- Add delete button here -->
|
||||||
<el-button type="danger" icon="Delete" circle @click="removeGroupElement(groupIndex, positionIndex)"/>
|
<el-button type="danger" icon="Delete" circle @click="removeGroupElement(groupIndex, positionIndex)"/>
|
||||||
<el-button type="primary" icon="Plus" circle @click="addGroupElement(groupIndex)"/>
|
<!-- <el-button type="primary" icon="Plus" circle @click="addGroupElement(groupIndex)"/> -->
|
||||||
</div>
|
</div>
|
||||||
<div class="avatar-container">
|
<div class="avatar-container">
|
||||||
<!-- 头像图片 -->
|
<!-- 头像图片 -->
|
||||||
@ -89,34 +87,38 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
</div>
|
</div>
|
||||||
<div class="group-footer">
|
<div class="group-footer">
|
||||||
<div class="opt-left" data-html2canvas-ignore="true">
|
<div class="group-opt" data-html2canvas-ignore="true">
|
||||||
|
<div class="opt-left">
|
||||||
<el-button type="primary" icon="CopyDocument" @click="copy(group.details)">{{ t('Copy') }}</el-button>
|
<el-button type="primary" icon="CopyDocument" @click="copy(group.details)">{{ t('Copy') }}</el-button>
|
||||||
<el-button type="primary" icon="Document" @click="paste(groupIndex,'details')">{{
|
<el-button type="primary" icon="Document" @click="paste(groupIndex,'details')">{{
|
||||||
t('Paste')
|
t('Paste')
|
||||||
}}
|
}}
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
<QuillEditor v-model:content="group.details" contentType="html" theme="snow" :toolbar="toolbarOptions"/>
|
</div>
|
||||||
|
<QuillEditor ref="detailsEditor" v-model:content="group.details" contentType="html" theme="snow" :toolbar="toolbarOptions" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="divider-horizontal"></div>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
</draggable>
|
</draggable>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import {ref, reactive, toRefs} from 'vue';
|
import {ref, reactive, toRefs, nextTick} from 'vue';
|
||||||
import draggable from 'vuedraggable';
|
import draggable from 'vuedraggable';
|
||||||
import ShikigamiSelect from './ShikigamiSelect.vue';
|
import ShikigamiSelect from './ShikigamiSelect.vue';
|
||||||
import ShikigamiProperty from './ShikigamiProperty.vue';
|
import ShikigamiProperty from './ShikigamiProperty.vue';
|
||||||
import html2canvas from 'html2canvas';
|
import html2canvas from 'html2canvas';
|
||||||
import {useI18n} from 'vue-i18n'
|
import {useI18n} from 'vue-i18n'
|
||||||
import {QuillEditor} from '@vueup/vue-quill'
|
import { Quill, QuillEditor } from '@vueup/vue-quill'
|
||||||
|
import '@vueup/vue-quill/dist/vue-quill.bubble.css'
|
||||||
import '@vueup/vue-quill/dist/vue-quill.snow.css' // 引入样式文件
|
import '@vueup/vue-quill/dist/vue-quill.snow.css' // 引入样式文件
|
||||||
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
import * as ElementPlusIconsVue from '@element-plus/icons-vue'
|
||||||
import shikigamiData from '../data/Shikigami.json';
|
import shikigamiData from '../data/Shikigami.json';
|
||||||
@ -151,30 +153,48 @@ const copy = (str) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const paste = (groupIndex, type) => {
|
const paste = (groupIndex, type) => {
|
||||||
|
console.log("paste", groupIndex, type, clipboard.value)
|
||||||
if ('shortDescription' == type)
|
if ('shortDescription' == type)
|
||||||
props.groups[groupIndex].shortDescription = clipboard.value
|
props.groups[groupIndex].shortDescription = clipboard.value
|
||||||
else if ('details' == type)
|
else if ('details' == type)
|
||||||
props.groups[groupIndex].details = clipboard.value
|
props.groups[groupIndex].details = clipboard.value
|
||||||
}
|
}
|
||||||
|
|
||||||
// 定义工具栏选项
|
// 自定义字体注册
|
||||||
const toolbarOptions = [
|
const registerFonts = () => {
|
||||||
|
const Font = Quill.import('attributors/style/font')
|
||||||
|
Font.whitelist = ['SimSun', 'SimHei', 'KaiTi', 'FangSong', 'Microsoft YaHei', 'PingFang SC']
|
||||||
|
Quill.register(Font, true)
|
||||||
|
}
|
||||||
|
|
||||||
[{'color': []}, {'background': []}],
|
// 自定义字号注册
|
||||||
|
const registerSizes = () => {
|
||||||
|
const Size = Quill.import('attributors/style/size')
|
||||||
|
Size.whitelist = ['12px', '14px', '16px', '18px', '21px', '29px', '32px', '34px']
|
||||||
|
Quill.register(Size, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行注册
|
||||||
|
registerFonts()
|
||||||
|
registerSizes()
|
||||||
|
|
||||||
|
// 工具栏配置
|
||||||
|
const toolbarOptions = ref([
|
||||||
|
[{ font: ['SimSun', 'SimHei', 'KaiTi', 'FangSong', 'Microsoft YaHei', 'PingFang SC'] }],
|
||||||
|
[{ header: 1 }, { header: 2 }],
|
||||||
|
[{ size: ['12px', '14px', '16px', '18px', '21px', '29px', '32px', '34px'] }],
|
||||||
['bold', 'italic', 'underline', 'strike'],
|
['bold', 'italic', 'underline', 'strike'],
|
||||||
|
[{ color: [] }, { background: [] }],
|
||||||
// ['blockquote', 'code-block'],
|
// ['blockquote', 'code-block'],
|
||||||
// ['link', 'image', 'video', 'formula'],
|
[ { list: 'bullet' }, { list: 'ordered' }, {'list': 'check'}],
|
||||||
[{'header': 1}, {'header': 2}],
|
|
||||||
[{'list': 'ordered'}, {'list': 'bullet'}, {'list': 'check'}],
|
[{ indent: '-1' }, { indent: '+1' }],
|
||||||
// [{ 'script': 'sub'}, { 'script': 'super' }],
|
[{ align: [] }],
|
||||||
[{'indent': '-1'}, {'indent': '+1'}],
|
[{ direction: 'rtl' }],
|
||||||
// [{ 'size': ['small', false, 'large', 'huge'] }],
|
// [{ header: [1, 2, 3, 4, 5, 6, false] }],
|
||||||
// [{ 'header': [1, 2, 3, 4, 5, 6, false] }],
|
// ['link', 'image', 'video'],
|
||||||
// [{ 'font': [] }],
|
|
||||||
[{'align': []}],
|
|
||||||
[{'direction': 'rtl'}],
|
|
||||||
// ['clean']
|
// ['clean']
|
||||||
];
|
] as const)
|
||||||
|
|
||||||
// 定义方法
|
// 定义方法
|
||||||
const closeSelectShikigami = () => {
|
const closeSelectShikigami = () => {
|
||||||
@ -192,7 +212,7 @@ const editShikigami = (groupIndex, positionIndex) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const updateShikigami = (shikigami) => {
|
const updateShikigami = (shikigami) => {
|
||||||
console.log("parent====> ", shikigami);
|
console.log("parent====> ", shikigami, state);
|
||||||
state.showSelectShikigami = false;
|
state.showSelectShikigami = false;
|
||||||
|
|
||||||
const oldProperties = props.groups[state.groupIndex].groupInfo[state.positionIndex].properties;
|
const oldProperties = props.groups[state.groupIndex].groupInfo[state.positionIndex].properties;
|
||||||
@ -263,10 +283,21 @@ const addGroup = () => {
|
|||||||
groupInfo: [{}, {}, {}, {}, {}],
|
groupInfo: [{}, {}, {}, {}, {}],
|
||||||
details: ''
|
details: ''
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const container = document.getElementById('main-container');
|
||||||
|
|
||||||
|
|
||||||
|
nextTick(() => {
|
||||||
|
container.scrollTo({
|
||||||
|
top: container.scrollHeight,
|
||||||
|
behavior: 'smooth' // 可选平滑滚动
|
||||||
|
});
|
||||||
|
})
|
||||||
};
|
};
|
||||||
|
|
||||||
const addGroupElement = (groupIndex) => {
|
const addGroupElement = (groupIndex) => {
|
||||||
props.groups[groupIndex].groupInfo.push({});
|
props.groups[groupIndex].groupInfo.push({});
|
||||||
|
editShikigami(groupIndex, props.groups[groupIndex].groupInfo.length - 1);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -331,8 +362,30 @@ const importGroups = (file) => {
|
|||||||
reader.readAsText(file);
|
reader.readAsText(file);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 定义 QuillEditor 的 ref
|
||||||
|
const shortDescriptionEditor = ref<InstanceType<typeof QuillEditor>>()
|
||||||
|
const detailsEditor = ref<InstanceType<typeof QuillEditor>>()
|
||||||
|
|
||||||
|
// 保存方法
|
||||||
|
const saveQuillDesc = async (): Promise<string> => {
|
||||||
|
if (!shortDescriptionEditor.value) {
|
||||||
|
throw new Error('Quill editor instance not found')
|
||||||
|
}
|
||||||
|
return shortDescriptionEditor.value.getHTML()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 保存方法
|
||||||
|
const saveQuillDetail = async (): Promise<string> => {
|
||||||
|
if (!detailsEditor.value) {
|
||||||
|
throw new Error('Quill detailsEditor instance not found')
|
||||||
|
}
|
||||||
|
return detailsEditor.value.getHTML()
|
||||||
|
}
|
||||||
|
|
||||||
// 暴露方法给父组件
|
// 暴露方法给父组件
|
||||||
defineExpose({
|
defineExpose({
|
||||||
|
saveQuillDesc,
|
||||||
|
saveQuillDetail,
|
||||||
exportGroups,
|
exportGroups,
|
||||||
importGroups
|
importGroups
|
||||||
});
|
});
|
||||||
@ -388,11 +441,24 @@ defineExpose({
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.group-item {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.group-body {
|
.group-body {
|
||||||
padding: 20px;
|
padding: 20px;
|
||||||
width: 80%;
|
width: 80%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 水平分割线 */
|
||||||
|
.divider-horizontal {
|
||||||
|
border: 0;
|
||||||
|
height: 1px;
|
||||||
|
background: #e0e0e0;
|
||||||
|
margin: 24px 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.body-content {
|
.body-content {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -430,6 +496,7 @@ defineExpose({
|
|||||||
.opt-btn {
|
.opt-btn {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0px;
|
top: 0px;
|
||||||
|
right: 0px;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
}
|
}
|
||||||
@ -450,3 +517,132 @@ defineExpose({
|
|||||||
}
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.ql-container {
|
||||||
|
border-bottom-left-radius: 5px;
|
||||||
|
border-bottom-right-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-toolbar {
|
||||||
|
border-top-left-radius: 5px;
|
||||||
|
border-top-right-radius: 5px;
|
||||||
|
|
||||||
|
.ql-tooltip[data-mode="link"]::before {
|
||||||
|
content: "链接地址:";
|
||||||
|
}
|
||||||
|
.ql-tooltip[data-mode="video"]::before {
|
||||||
|
content: "视频地址:";
|
||||||
|
}
|
||||||
|
.ql-tooltip.ql-editing {
|
||||||
|
a.ql-action::after {
|
||||||
|
content: "保存";
|
||||||
|
border-right: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-font {
|
||||||
|
.ql-picker-label[data-value=SimSun]::before,
|
||||||
|
.ql-picker-item[data-value=SimSun]::before {
|
||||||
|
content: "宋体";
|
||||||
|
font-family: SimSun;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value=SimHei]::before,
|
||||||
|
.ql-picker-item[data-value=SimHei]::before {
|
||||||
|
content: "黑体";
|
||||||
|
font-family: SimHei;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value=KaiTi]::before,
|
||||||
|
.ql-picker-item[data-value=KaiTi]::before {
|
||||||
|
content: "楷体";
|
||||||
|
font-family: KaiTi;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value=FangSong]::before,
|
||||||
|
.ql-picker-item[data-value=FangSong]::before {
|
||||||
|
content: "仿宋";
|
||||||
|
font-family: FangSong;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="Microsoft YaHei"]::before,
|
||||||
|
.ql-picker-item[data-value="Microsoft YaHei"]::before {
|
||||||
|
content: "微软雅黑";
|
||||||
|
font-family: 'Microsoft YaHei';
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="PingFang SC"]::before,
|
||||||
|
.ql-picker-item[data-value="PingFang SC"]::before {
|
||||||
|
content: "苹方";
|
||||||
|
font-family: 'PingFang SC';
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ql-picker.ql-size {
|
||||||
|
.ql-picker-label::before,
|
||||||
|
.ql-picker-item::before {
|
||||||
|
font-size: 14px !important;
|
||||||
|
content: "五号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="12px"]::before {
|
||||||
|
content: "小五" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="12px"]::before {
|
||||||
|
font-size: 12px;
|
||||||
|
content: "小五" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="16px"]::before {
|
||||||
|
content: "小四" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="16px"]::before {
|
||||||
|
font-size: 16px;
|
||||||
|
content: "小四" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="18px"]::before {
|
||||||
|
content: "四号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="18px"]::before {
|
||||||
|
font-size: 18px;
|
||||||
|
content: "四号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="21px"]::before {
|
||||||
|
content: "三号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="21px"]::before {
|
||||||
|
font-size: 21px;
|
||||||
|
content: "三号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="24px"]::before {
|
||||||
|
content: "小二" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="24px"]::before {
|
||||||
|
font-size: 24px;
|
||||||
|
content: "小二" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="29px"]::before {
|
||||||
|
content: "二号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="29px"]::before {
|
||||||
|
font-size: 29px;
|
||||||
|
content: "二号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="32px"]::before {
|
||||||
|
content: "小一" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="32px"]::before {
|
||||||
|
font-size: 32px;
|
||||||
|
content: "小一" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-label[data-value="34px"]::before {
|
||||||
|
content: "一号" !important;
|
||||||
|
}
|
||||||
|
.ql-picker-item[data-value="34px"]::before {
|
||||||
|
font-size: 34px;
|
||||||
|
content: "一号" !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
183
src/data/filesStoreExample.json
Normal file
183
src/data/filesStoreExample.json
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"label": "Welcome",
|
||||||
|
"name": "1",
|
||||||
|
"type":"PVE",
|
||||||
|
"visible": true,
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"shortDescription": "<h1>鬼灵歌姬</h1><h2><em>这是一个演示项目,用于测试显示6个式神的对齐效果</em></h2>",
|
||||||
|
"groupInfo": [
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/sp/372.png",
|
||||||
|
"name": "因幡辉夜姬",
|
||||||
|
"rarity": "SP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/356.png",
|
||||||
|
"name": "千姬",
|
||||||
|
"rarity": "SSR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/sp/554.png",
|
||||||
|
"name": "纺愿缘结神",
|
||||||
|
"rarity": "SP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/556.png",
|
||||||
|
"name": "天照",
|
||||||
|
"rarity": "SSR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/557.png",
|
||||||
|
"name": "伊邪那美",
|
||||||
|
"rarity": "SSR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/sp/367.png",
|
||||||
|
"name": "绘世花鸟卷",
|
||||||
|
"rarity": "SP"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"details": "<h2><strong>开局因幡普攻主怪后锁二</strong></h2>"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shortDescription": "<h1>魂土15秒</h1><p><em>相同式神编辑不同属性</em></p>",
|
||||||
|
"groupInfo": [
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/364.png",
|
||||||
|
"name": "阿修罗",
|
||||||
|
"rarity": "SSR",
|
||||||
|
"properties": {
|
||||||
|
"edit": true,
|
||||||
|
"yuhun": {
|
||||||
|
"yuhunSetEffect": [
|
||||||
|
{
|
||||||
|
"name": "狂骨",
|
||||||
|
"shortName": "狂",
|
||||||
|
"type": "attack",
|
||||||
|
"avatar": "/assets/Yuhun/狂骨.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "荒骷髅",
|
||||||
|
"shortName": "荒",
|
||||||
|
"type": "PVE",
|
||||||
|
"avatar": "/assets/Yuhun/荒骷髅.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"target": "1",
|
||||||
|
"property2": [
|
||||||
|
"Attack"
|
||||||
|
],
|
||||||
|
"property4": [
|
||||||
|
"Attack"
|
||||||
|
],
|
||||||
|
"property6": [
|
||||||
|
"Crit",
|
||||||
|
"CritDamage"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"levelRequired": "40",
|
||||||
|
"speed": "",
|
||||||
|
"skillRequiredMode": "all",
|
||||||
|
"skillRequired": [
|
||||||
|
"5",
|
||||||
|
"5",
|
||||||
|
"5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/364.png",
|
||||||
|
"name": "阿修罗",
|
||||||
|
"rarity": "SSR",
|
||||||
|
"properties": {
|
||||||
|
"edit": true,
|
||||||
|
"yuhun": {
|
||||||
|
"yuhunSetEffect": [
|
||||||
|
{
|
||||||
|
"name": "狂骨",
|
||||||
|
"shortName": "狂",
|
||||||
|
"type": "attack",
|
||||||
|
"avatar": "/assets/Yuhun/狂骨.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "鬼灵歌伎",
|
||||||
|
"shortName": "歌伎",
|
||||||
|
"type": "PVE",
|
||||||
|
"avatar": "/assets/Yuhun/鬼灵歌伎.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"target": "0",
|
||||||
|
"property2": [
|
||||||
|
"Attack"
|
||||||
|
],
|
||||||
|
"property4": [
|
||||||
|
"Attack"
|
||||||
|
],
|
||||||
|
"property6": [
|
||||||
|
"Crit",
|
||||||
|
"CritDamage"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"levelRequired": "40",
|
||||||
|
"speed": "",
|
||||||
|
"skillRequiredMode": "all",
|
||||||
|
"skillRequired": [
|
||||||
|
"5",
|
||||||
|
"5",
|
||||||
|
"5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/370.png",
|
||||||
|
"name": "饭笥",
|
||||||
|
"rarity": "SSR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/ssr/369.png",
|
||||||
|
"name": "食灵",
|
||||||
|
"rarity": "SSR"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"avatar": "/assets/Shikigami/r/205.png",
|
||||||
|
"name": "座敷童子",
|
||||||
|
"rarity": "R"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"details": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Test",
|
||||||
|
"name": "2",
|
||||||
|
"visible": true,
|
||||||
|
"type":"PVE",
|
||||||
|
"groups": [
|
||||||
|
{
|
||||||
|
"shortDescription": "<h1>御魂·悲鸣</h1><p>这是一个演示项目,用于测试不同标签页的切换效果</p>",
|
||||||
|
"groupInfo": [
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"details": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"shortDescription": "",
|
||||||
|
"groupInfo": [
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
],
|
||||||
|
"details": ""
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
@ -1,4 +1,19 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"version": "2.2.0",
|
||||||
|
"date": "2025-03-21",
|
||||||
|
"changes": [
|
||||||
|
"优化文本编辑显示",
|
||||||
|
"增加缓存机制,支持在未保存的情况下恢复数据,水印设置信息"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"version": "2.1.0",
|
||||||
|
"date": "2025-03-19",
|
||||||
|
"changes": [
|
||||||
|
"增加式神搜索功能"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"date": "2025-03-20",
|
"date": "2025-03-20",
|
||||||
|
@ -2,8 +2,13 @@
|
|||||||
"import": "导入",
|
"import": "导入",
|
||||||
"export": "导出",
|
"export": "导出",
|
||||||
"setWatermark": "设置水印",
|
"setWatermark": "设置水印",
|
||||||
|
"loadExample": "加载样例",
|
||||||
|
"updateLog":"更新日志",
|
||||||
|
"feedback":"问题反馈",
|
||||||
"Copy": "复制",
|
"Copy": "复制",
|
||||||
"Paste": "粘贴",
|
"Paste": "粘贴",
|
||||||
|
"AddGroup": "新增小队",
|
||||||
|
"AddShikigami": "新增式神",
|
||||||
"editProperties": "配置属性",
|
"editProperties": "配置属性",
|
||||||
"prepareCapture": "生成截图",
|
"prepareCapture": "生成截图",
|
||||||
"yuhunSelect": "请选择御魂",
|
"yuhunSelect": "请选择御魂",
|
||||||
|
@ -16,6 +16,7 @@ import zh from './locales/zh.json'
|
|||||||
import ja from './locales/ja.json'
|
import ja from './locales/ja.json'
|
||||||
|
|
||||||
import { createPinia } from 'pinia' // 导入 Pinia
|
import { createPinia } from 'pinia' // 导入 Pinia
|
||||||
|
import {useFilesStore} from "@/ts/files";
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
@ -59,4 +60,8 @@ app.use(pinia) // 使用 Pinia
|
|||||||
.use(i18n)
|
.use(i18n)
|
||||||
.use(ElementPlus)
|
.use(ElementPlus)
|
||||||
.use(Vue3DraggableResizable)
|
.use(Vue3DraggableResizable)
|
||||||
.mount('#app')
|
.mount('#app')
|
||||||
|
|
||||||
|
const filesStore = useFilesStore();
|
||||||
|
filesStore.setupAutoSave();
|
||||||
|
filesStore.initializeWithPrompt();
|
250
src/ts/files.ts
250
src/ts/files.ts
@ -3,197 +3,75 @@ import {ElMessageBox} from "element-plus";
|
|||||||
import {useGlobalMessage} from "./useGlobalMessage";
|
import {useGlobalMessage} from "./useGlobalMessage";
|
||||||
|
|
||||||
const { showMessage } = useGlobalMessage();
|
const { showMessage } = useGlobalMessage();
|
||||||
export const useFilesStore = defineStore('files', {
|
|
||||||
state: () => ({
|
function getDefaultState() {
|
||||||
fileList: [
|
return {
|
||||||
{
|
fileList: [{
|
||||||
"label": "Welcome",
|
"label": "File 1",
|
||||||
"name": "1",
|
"name": "1",
|
||||||
"type":"PVE",
|
"visible": true,
|
||||||
"visible": true,
|
"type":"PVE",
|
||||||
"groups": [
|
"groups": [
|
||||||
{
|
{
|
||||||
"shortDescription": "<h1>鬼灵歌姬</h1><h2><em>这是一个演示项目,用于测试显示6个式神的对齐效果</em></h2>",
|
"shortDescription": "",
|
||||||
"groupInfo": [
|
"groupInfo": [
|
||||||
{
|
{}, {}, {}, {}, {}
|
||||||
"avatar": "/assets/Shikigami/sp/372.png",
|
],
|
||||||
"name": "因幡辉夜姬",
|
"details": ""
|
||||||
"rarity": "SP"
|
}
|
||||||
},
|
]
|
||||||
{
|
}],
|
||||||
"avatar": "/assets/Shikigami/ssr/356.png",
|
|
||||||
"name": "千姬",
|
|
||||||
"rarity": "SSR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/sp/554.png",
|
|
||||||
"name": "纺愿缘结神",
|
|
||||||
"rarity": "SP"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/ssr/556.png",
|
|
||||||
"name": "天照",
|
|
||||||
"rarity": "SSR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/ssr/557.png",
|
|
||||||
"name": "伊邪那美",
|
|
||||||
"rarity": "SSR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/sp/367.png",
|
|
||||||
"name": "绘世花鸟卷",
|
|
||||||
"rarity": "SP"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"details": "<h2><strong>开局因幡普攻主怪后锁二</strong></h2>"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"shortDescription": "<h1>魂土15秒</h1><p><em>相同式神编辑不同属性</em></p>",
|
|
||||||
"groupInfo": [
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/ssr/364.png",
|
|
||||||
"name": "阿修罗",
|
|
||||||
"rarity": "SSR",
|
|
||||||
"properties": {
|
|
||||||
"edit": true,
|
|
||||||
"yuhun": {
|
|
||||||
"yuhunSetEffect": [
|
|
||||||
{
|
|
||||||
"name": "狂骨",
|
|
||||||
"shortName": "狂",
|
|
||||||
"type": "attack",
|
|
||||||
"avatar": "/assets/Yuhun/狂骨.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "荒骷髅",
|
|
||||||
"shortName": "荒",
|
|
||||||
"type": "PVE",
|
|
||||||
"avatar": "/assets/Yuhun/荒骷髅.png"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"target": "1",
|
|
||||||
"property2": [
|
|
||||||
"Attack"
|
|
||||||
],
|
|
||||||
"property4": [
|
|
||||||
"Attack"
|
|
||||||
],
|
|
||||||
"property6": [
|
|
||||||
"Crit",
|
|
||||||
"CritDamage"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"levelRequired": "40",
|
|
||||||
"speed": "",
|
|
||||||
"skillRequiredMode": "all",
|
|
||||||
"skillRequired": [
|
|
||||||
"5",
|
|
||||||
"5",
|
|
||||||
"5"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/ssr/364.png",
|
|
||||||
"name": "阿修罗",
|
|
||||||
"rarity": "SSR",
|
|
||||||
"properties": {
|
|
||||||
"edit": true,
|
|
||||||
"yuhun": {
|
|
||||||
"yuhunSetEffect": [
|
|
||||||
{
|
|
||||||
"name": "狂骨",
|
|
||||||
"shortName": "狂",
|
|
||||||
"type": "attack",
|
|
||||||
"avatar": "/assets/Yuhun/狂骨.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "鬼灵歌伎",
|
|
||||||
"shortName": "歌伎",
|
|
||||||
"type": "PVE",
|
|
||||||
"avatar": "/assets/Yuhun/鬼灵歌伎.png"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"target": "0",
|
|
||||||
"property2": [
|
|
||||||
"Attack"
|
|
||||||
],
|
|
||||||
"property4": [
|
|
||||||
"Attack"
|
|
||||||
],
|
|
||||||
"property6": [
|
|
||||||
"Crit",
|
|
||||||
"CritDamage"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"levelRequired": "40",
|
|
||||||
"speed": "",
|
|
||||||
"skillRequiredMode": "all",
|
|
||||||
"skillRequired": [
|
|
||||||
"5",
|
|
||||||
"5",
|
|
||||||
"5"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/ssr/370.png",
|
|
||||||
"name": "饭笥",
|
|
||||||
"rarity": "SSR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/ssr/369.png",
|
|
||||||
"name": "食灵",
|
|
||||||
"rarity": "SSR"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"avatar": "/assets/Shikigami/r/205.png",
|
|
||||||
"name": "座敷童子",
|
|
||||||
"rarity": "R"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"details": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"label": "Test",
|
|
||||||
"name": "2",
|
|
||||||
"visible": true,
|
|
||||||
"type":"PVE",
|
|
||||||
"groups": [
|
|
||||||
{
|
|
||||||
"shortDescription": "<h1>御魂·悲鸣</h1><p>这是一个演示项目,用于测试不同标签页的切换效果</p>",
|
|
||||||
"groupInfo": [
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{}
|
|
||||||
],
|
|
||||||
"details": ""
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"shortDescription": "",
|
|
||||||
"groupInfo": [
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
{}
|
|
||||||
],
|
|
||||||
"details": ""
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
activeFile: "1",
|
activeFile: "1",
|
||||||
}),
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function saveStateToLocalStorage(state) {
|
||||||
|
localStorage.setItem('filesStore', JSON.stringify(state));
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearFilesStoreLocalStorage() {
|
||||||
|
localStorage.removeItem('filesStore')
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadStateFromLocalStorage() {
|
||||||
|
return JSON.parse(localStorage.getItem('filesStore'));
|
||||||
|
}
|
||||||
|
|
||||||
|
export const useFilesStore = defineStore('files', {
|
||||||
|
state: () => getDefaultState(),
|
||||||
getters: {
|
getters: {
|
||||||
visibleFiles: (state) => state.fileList.filter(file => file.visible),
|
visibleFiles: (state) => state.fileList.filter(file => file.visible),
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
initializeWithPrompt() {
|
||||||
|
const savedState = loadStateFromLocalStorage();
|
||||||
|
const defaultState = getDefaultState();
|
||||||
|
|
||||||
|
const isSame = JSON.stringify(savedState) === JSON.stringify(defaultState);
|
||||||
|
if (savedState && !isSame) {
|
||||||
|
ElMessageBox.confirm(
|
||||||
|
'检测到有未保存的旧数据,是否恢复?',
|
||||||
|
'提示',
|
||||||
|
{
|
||||||
|
confirmButtonText: '恢复',
|
||||||
|
cancelButtonText: '不恢复',
|
||||||
|
type: 'warning',
|
||||||
|
}
|
||||||
|
).then(() => {
|
||||||
|
this.fileList = savedState.fileList || [];
|
||||||
|
this.activeFile = savedState.activeFile || "1";
|
||||||
|
showMessage('success', '数据已恢复');
|
||||||
|
}).catch(() => {
|
||||||
|
clearFilesStoreLocalStorage();
|
||||||
|
showMessage('info', '选择了不恢复旧数据');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
setupAutoSave() {
|
||||||
|
setInterval(() => {
|
||||||
|
saveStateToLocalStorage(this.$state);
|
||||||
|
}, 30000); // 设置间隔时间为30秒
|
||||||
|
},
|
||||||
addFile(file) {
|
addFile(file) {
|
||||||
this.fileList.push({...file, visible: true});
|
this.fileList.push({...file, visible: true});
|
||||||
this.activeFile = file.name;
|
this.activeFile = file.name;
|
||||||
|
Reference in New Issue
Block a user