save2
This commit is contained in:
@@ -324,112 +324,6 @@
|
||||
toggleEl('#qqDialog', true)
|
||||
}
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// 旧域名地址
|
||||
var OLD_ORIGIN = 'https://2study.top';
|
||||
|
||||
// 需要迁移的 IndexedDB key
|
||||
var IDB_KEYS = [
|
||||
'type-words-app-version',
|
||||
'typing-word-dict',
|
||||
'typing-word-setting',
|
||||
'typing-word-files'
|
||||
];
|
||||
|
||||
// 需要迁移的 localStorage key
|
||||
var LS_KEYS = [
|
||||
'PracticeSaveWord',
|
||||
'PracticeSaveArticle'
|
||||
];
|
||||
|
||||
// 1️⃣ 动态加载 idb-keyval
|
||||
function loadIDBKeyval() {
|
||||
return new Promise((resolve) => {
|
||||
if (window.idbKeyval) return resolve(window.idbKeyval);
|
||||
|
||||
var script = document.createElement('script');
|
||||
script.src = 'https://cdn.jsdelivr.net/npm/idb-keyval@6.2.2/dist/umd.js';
|
||||
script.onload = () => resolve(window.idbKeyval);
|
||||
document.head.appendChild(script);
|
||||
});
|
||||
}
|
||||
|
||||
// 创建迁移窗口并接收数据
|
||||
async function migrateFromOldSite() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
const db = await loadIDBKeyval();
|
||||
|
||||
const migrateWin = window.open(`${OLD_ORIGIN}/migrate.html`, '_blank', 'width=400,height=400');
|
||||
|
||||
if (!migrateWin) return reject('弹窗被阻止,请允许弹窗');
|
||||
|
||||
function onMessage(event) {
|
||||
if (event.origin !== OLD_ORIGIN) return;
|
||||
if (event.data?.type !== 'MIGRATION_RESULT') return;
|
||||
|
||||
const payload = event.data.payload;
|
||||
|
||||
console.log('payload', payload);
|
||||
|
||||
// 写入 localStorage
|
||||
LS_KEYS.forEach(key => {
|
||||
if (payload.localStorage[key] !== undefined) {
|
||||
localStorage.setItem(key, payload.localStorage[key]);
|
||||
}
|
||||
});
|
||||
|
||||
// 写入 IndexedDB
|
||||
(async () => {
|
||||
for (let key of IDB_KEYS) {
|
||||
if (payload.indexedDB[key] !== undefined) {
|
||||
await db.set(key, payload.indexedDB[key]);
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener('message', onMessage);
|
||||
resolve(true);
|
||||
})();
|
||||
}
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
|
||||
// 等窗口加载完毕后发请求
|
||||
const timer = setInterval(() => {
|
||||
if (!migrateWin || migrateWin.closed) {
|
||||
clearInterval(timer);
|
||||
reject('迁移窗口已关闭');
|
||||
} else {
|
||||
try {
|
||||
migrateWin.postMessage({type: 'REQUEST_MIGRATION_DATA'}, OLD_ORIGIN);
|
||||
} catch (e) {
|
||||
// 跨域安全错误忽略,等窗口完全加载后再试
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
if (location.href === 'https://typewords.cc/') {
|
||||
window.addEventListener("DOMContentLoaded", () => {
|
||||
// 3️⃣ 自动执行迁移(只执行一次)
|
||||
(async () => {
|
||||
if (localStorage.getItem('__migrated_from_2study_top__')) return;
|
||||
|
||||
console.log('开始从旧域名迁移数据…');
|
||||
|
||||
try {
|
||||
await migrateFromOldSite();
|
||||
localStorage.setItem('__migrated_from_2study_top__', '1');
|
||||
console.log('迁移完成');
|
||||
} catch (e) {
|
||||
console.error('迁移失败', e);
|
||||
}
|
||||
})();
|
||||
});
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="wrapper">
|
||||
|
||||
59
src/App.vue
59
src/App.vue
@@ -1,17 +1,18 @@
|
||||
<script setup lang="ts">
|
||||
import { onMounted, watch } from "vue";
|
||||
import { BaseState, useBaseStore } from "@/stores/base.ts";
|
||||
import { useRuntimeStore } from "@/stores/runtime.ts";
|
||||
import { useSettingStore } from "@/stores/setting.ts";
|
||||
import {onMounted, watch} from "vue";
|
||||
import {BaseState, useBaseStore} from "@/stores/base.ts";
|
||||
import {useRuntimeStore} from "@/stores/runtime.ts";
|
||||
import {useSettingStore} from "@/stores/setting.ts";
|
||||
import useTheme from "@/hooks/theme.ts";
|
||||
import { loadJsLib, shakeCommonDict } from "@/utils";
|
||||
import { get, set } from 'idb-keyval'
|
||||
import {loadJsLib, shakeCommonDict} from "@/utils";
|
||||
import {get, set} from 'idb-keyval'
|
||||
|
||||
import { useRoute } from "vue-router";
|
||||
import { DictId } from "@/types/types.ts";
|
||||
import { APP_VERSION, AppEnv, LOCAL_FILE_KEY, SAVE_DICT_KEY, SAVE_SETTING_KEY } from "@/config/env.ts";
|
||||
import { syncSetting } from "@/apis";
|
||||
import { useUserStore } from "@/stores/auth.ts";
|
||||
import {useRoute} from "vue-router";
|
||||
import {DictId} from "@/types/types.ts";
|
||||
import {APP_VERSION, AppEnv, LOCAL_FILE_KEY, Origin, SAVE_DICT_KEY, SAVE_SETTING_KEY} from "@/config/env.ts";
|
||||
import {syncSetting} from "@/apis";
|
||||
import {useUserStore} from "@/stores/auth.ts";
|
||||
import MigrateDialog from "@/pages/MigrateDialog.vue";
|
||||
|
||||
const store = useBaseStore()
|
||||
const runtimeStore = useRuntimeStore()
|
||||
@@ -77,31 +78,16 @@ async function init() {
|
||||
|
||||
onMounted(init)
|
||||
|
||||
onMounted(()=>{
|
||||
return
|
||||
// const iframe = document.createElement('iframe');
|
||||
// iframe.style.display = 'none';
|
||||
// iframe.src = `https://2study.top/migrate.html`;
|
||||
// function onMessage(event) {
|
||||
// if (event.data?.type !== 'MIGRATION_RESULT') return;
|
||||
//
|
||||
// const payload = event.data.payload;
|
||||
// console.log('payload',payload)
|
||||
// }
|
||||
//
|
||||
// window.addEventListener('message', onMessage);
|
||||
// iframe.onload = () => {
|
||||
// setTimeout(()=>{
|
||||
// iframe.contentWindow.postMessage({type: 'REQUEST_MIGRATION_DATA'}, 'https://2study.top');
|
||||
// },3000)
|
||||
// };
|
||||
// document.body.appendChild(iframe);
|
||||
//
|
||||
// (async () => {
|
||||
// const db = await loadIDBKeyval(); // 确保 idb-keyval 已经加载
|
||||
// const data = await readAllStorageForMigration(db);
|
||||
// console.log('data',data)
|
||||
// })()
|
||||
|
||||
//迁移数据
|
||||
let showTransfer = $ref(false)
|
||||
onMounted(() => {
|
||||
if (new URLSearchParams(window.location.search).get('from_old_site') === '1' && location.origin === Origin) {
|
||||
if (localStorage.getItem('__migrated_from_2study_top__')) return;
|
||||
setTimeout(() => {
|
||||
showTransfer = true
|
||||
}, 1000)
|
||||
}
|
||||
})
|
||||
|
||||
// let transitionName = $ref('go')
|
||||
@@ -136,4 +122,5 @@ onMounted(()=>{
|
||||
<!-- </transition>-->
|
||||
<!-- </router-view>-->
|
||||
<router-view></router-view>
|
||||
<MigrateDialog v-model="showTransfer"/>
|
||||
</template>
|
||||
111
src/pages/MigrateDialog.vue
Normal file
111
src/pages/MigrateDialog.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<script setup lang="ts">
|
||||
|
||||
import {Origin} from "@/config/env.ts";
|
||||
import BaseButton from "@/components/BaseButton.vue";
|
||||
import {set} from 'idb-keyval'
|
||||
import {defineAsyncComponent} from "vue";
|
||||
import Toast from "@/components/base/toast/Toast.ts";
|
||||
|
||||
const Dialog = defineAsyncComponent(() => import('@/components/dialog/Dialog.vue'))
|
||||
|
||||
const model = defineModel()
|
||||
|
||||
async function migrateFromOldSite() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
// 旧域名地址
|
||||
var OLD_ORIGIN = 'https://2study.top';
|
||||
// 需要迁移的 IndexedDB key
|
||||
var IDB_KEYS = [
|
||||
'type-words-app-version',
|
||||
'typing-word-dict',
|
||||
'typing-word-setting',
|
||||
'typing-word-files'
|
||||
];
|
||||
// 需要迁移的 localStorage key
|
||||
var LS_KEYS = [
|
||||
'PracticeSaveWord',
|
||||
'PracticeSaveArticle'
|
||||
];
|
||||
const migrateWin = window.open(`${OLD_ORIGIN}/migrate.html`, '_blank', 'width=400,height=400');
|
||||
|
||||
if (!migrateWin) return reject('弹窗被阻止,请在网址输入栏最右边,点击允许弹窗');
|
||||
|
||||
async function onMessage(event) {
|
||||
if (event.origin !== OLD_ORIGIN) return;
|
||||
if (event.data?.type !== 'MIGRATION_RESULT') return;
|
||||
const payload = event.data.payload;
|
||||
console.log('payload', payload);
|
||||
|
||||
// 写入 localStorage
|
||||
LS_KEYS.forEach(key => {
|
||||
if (payload.localStorage[key] !== undefined) {
|
||||
localStorage.setItem(key, payload.localStorage[key]);
|
||||
}
|
||||
});
|
||||
|
||||
// 写入 IndexedDB
|
||||
for (let key of IDB_KEYS) {
|
||||
if (payload.indexedDB[key] !== undefined) {
|
||||
await set(key, payload.indexedDB[key]);
|
||||
}
|
||||
}
|
||||
|
||||
window.removeEventListener('message', onMessage);
|
||||
resolve(true);
|
||||
}
|
||||
|
||||
window.addEventListener('message', onMessage);
|
||||
|
||||
// 等窗口加载完毕后发请求
|
||||
const timer = setInterval(() => {
|
||||
if (!migrateWin || migrateWin.closed) {
|
||||
clearInterval(timer);
|
||||
reject('迁移窗口已关闭');
|
||||
} else {
|
||||
try {
|
||||
migrateWin.postMessage({type: 'REQUEST_MIGRATION_DATA'}, OLD_ORIGIN);
|
||||
} catch (e) {
|
||||
// 跨域安全错误忽略,等窗口完全加载后再试
|
||||
}
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
async function transfer() {
|
||||
try {
|
||||
await migrateFromOldSite();
|
||||
localStorage.setItem('__migrated_from_2study_top__', '1');
|
||||
console.log('迁移完成');
|
||||
Toast.success('迁移完成')
|
||||
model.value = false
|
||||
} catch (e) {
|
||||
Toast.error('迁移失败:' + e)
|
||||
console.error('迁移失败', e);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Dialog v-model="model" title="迁移数据">
|
||||
<div class="px-4 flex-col center text-align-center w-100">
|
||||
<h2>
|
||||
本网站已启用新域名 <span class="color-blue">{{ Origin }}</span>
|
||||
</h2>
|
||||
<h3>
|
||||
由于浏览器安全限制,新老网站数据无法互通,需要您手动点击转移数据
|
||||
</h3>
|
||||
<h3>
|
||||
<BaseButton
|
||||
size="large"
|
||||
@click="transfer">
|
||||
转移数据
|
||||
</BaseButton>
|
||||
</h3>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user