更新公告,水印保存,数据保存提示优化

pull/5/head
rookie4show 4 weeks ago
parent 39e55c2e38
commit 08bb1bdb7f
  1. 75
      src/components/Toolbar.vue
  2. 183
      src/data/filesStoreExample.json
  3. 4
      src/data/updateLog.json
  4. 3
      src/locales/zh.json
  5. 219
      src/ts/files.ts

@ -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.

@ -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,10 +1,10 @@
[ [
{ {
"version": "2.2.0", "version": "2.2.0",
"date": "2025-03-19", "date": "2025-03-21",
"changes": [ "changes": [
"优化文本编辑显示", "优化文本编辑显示",
"增加缓存机制,支持在未保存的情况下恢复数据" "增加缓存机制,支持在未保存的情况下恢复数据,水印设置信息"
] ]
}, },
{ {

@ -2,6 +2,9 @@
"import": "导入", "import": "导入",
"export": "导出", "export": "导出",
"setWatermark": "设置水印", "setWatermark": "设置水印",
"loadExample": "加载样例",
"updateLog":"更新日志",
"feedback":"问题反馈",
"Copy": "复制", "Copy": "复制",
"Paste": "粘贴", "Paste": "粘贴",
"AddGroup": "新增小队", "AddGroup": "新增小队",

@ -4,12 +4,33 @@ import {useGlobalMessage} from "./useGlobalMessage";
const { showMessage } = useGlobalMessage(); const { showMessage } = useGlobalMessage();
function getDefaultState() {
return {
fileList: [{
"label": "File 1",
"name": "1",
"visible": true,
"type":"PVE",
"groups": [
{
"shortDescription": "",
"groupInfo": [
{}, {}, {}, {}, {}
],
"details": ""
}
]
}],
activeFile: "1",
};
}
function saveStateToLocalStorage(state) { function saveStateToLocalStorage(state) {
localStorage.setItem('filesStore', JSON.stringify(state)); localStorage.setItem('filesStore', JSON.stringify(state));
} }
function clearLocalStorage() { function clearFilesStoreLocalStorage() {
localStorage.clear() localStorage.removeItem('filesStore')
} }
function loadStateFromLocalStorage() { function loadStateFromLocalStorage() {
@ -17,199 +38,17 @@ function loadStateFromLocalStorage() {
} }
export const useFilesStore = defineStore('files', { export const useFilesStore = defineStore('files', {
state: () => ({ state: () => getDefaultState(),
fileList: [
{
"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": ""
}
]
}
],
activeFile: "1",
}),
getters: { getters: {
visibleFiles: (state) => state.fileList.filter(file => file.visible), visibleFiles: (state) => state.fileList.filter(file => file.visible),
}, },
actions: { actions: {
initializeWithPrompt() { initializeWithPrompt() {
const savedState = loadStateFromLocalStorage(); const savedState = loadStateFromLocalStorage();
if (savedState) { const defaultState = getDefaultState();
const isSame = JSON.stringify(savedState) === JSON.stringify(defaultState);
if (savedState && !isSame) {
ElMessageBox.confirm( ElMessageBox.confirm(
'检测到有未保存的旧数据,是否恢复?', '检测到有未保存的旧数据,是否恢复?',
'提示', '提示',
@ -223,7 +62,7 @@ export const useFilesStore = defineStore('files', {
this.activeFile = savedState.activeFile || "1"; this.activeFile = savedState.activeFile || "1";
showMessage('success', '数据已恢复'); showMessage('success', '数据已恢复');
}).catch(() => { }).catch(() => {
clearLocalStorage(); clearFilesStoreLocalStorage();
showMessage('info', '选择了不恢复旧数据'); showMessage('info', '选择了不恢复旧数据');
}); });
} }

Loading…
Cancel
Save