数据备份1/2

This commit is contained in:
expdsn 2024-11-13 19:51:52 +08:00
parent 4101e83677
commit 9a74b31eac
7 changed files with 143 additions and 33 deletions

View File

@ -16,6 +16,7 @@ import useLayoutStore from './layout/useLayoutStore'
import WelcomePage from './layout/grid/WelcomePage'
import TomatoPage from './layout/grid/TomatoPage'
import useRouterStore from './useRouterStore'
import BackupRecovery from './user/BackupRecovery'
const Grid = asyncLoader(() => import('./layout/grid'))
const Fox = asyncLoader(() => import('./fox'))
const settings = useSettingsStore()
@ -50,14 +51,21 @@ const layout = useLayoutStore()
(layout.state.simple && settings.state.simpleModeShowString.includes('showDock'))
"
/>
<div class="fixed z-40 right-[14%] top-8" v-if="!layout.state.simple ||
(layout.state.simple && settings.state.simpleModeShowString.includes('showPet'))">
<div
class="fixed z-40 right-[14%] top-8"
v-if="
!layout.state.simple ||
(layout.state.simple && settings.state.simpleModeShowString.includes('showPet'))
"
>
<Fox />
</div>
<DirModal />
<GlobalMenu />
<WelcomePage></WelcomePage>
<TomatoPage></TomatoPage>
<BackupRecovery v-if="router.path === 'global-backup'"></BackupRecovery>
</div>
</template>

View File

@ -18,7 +18,7 @@ export default defineComponent(() => {
router.path.startsWith('widget-') ||
router.path === 'global-search' ||
router.path === 'global-adder' ||
router.path === 'global-background'
router.path === 'global-background'
)
const full = ref(false)
watch(router, () => {
@ -93,20 +93,21 @@ export default defineComponent(() => {
<AdderPage />
) : router.path === 'global-background' ? (
<BackgroundSwtich />
) : router.path.startsWith('widget-') ? (
(() => {
const name = router.path.split('-')[1]
const selected = widgetList.find((el) => el.name === name)
if (!selected)
return (
<div class="w-full h-full flex justify-center items-center text-black/80">
</div>
)
const compo = selected.modal
return <compo />
})()
) : null}
) :
router.path.startsWith('widget-') ? (
(() => {
const name = router.path.split('-')[1]
const selected = widgetList.find((el) => el.name === name)
if (!selected)
return (
<div class="w-full h-full flex justify-center items-center text-black/80">
</div>
)
const compo = selected.modal
return <compo />
})()
) : null}
</Transition>
</div>
</div>

View File

@ -20,7 +20,7 @@ export const apiBase = import.meta.env.PROD
// 后端 cdn 加速地址
export const cdnBase = import.meta.env.PROD ? apiBase : apiBase
// eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI2NzJkYjg5OGUxMjY5NDc1ODYwMmYwMTgifQ.8fpdr_HPgxyU0yr-8f6nGdbHYjsFRlBa2lvjc0Zhe-A
// 图片后缀名
export const imgArr = [
'bmp',

View File

@ -1,7 +1,7 @@
import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'
export type GlobalStr = 'search' | 'block' | 'adder' | 'login' | 'background'
export type GlobalStr = 'search' | 'block' | 'adder' | 'login' | 'background' | 'backup'
export type SettingStr =
| 'user'
| 'background'

View File

@ -0,0 +1,49 @@
import { defineComponent, ref, Transition } from 'vue'
import useRouterStore from '@/useRouterStore'
import { Radio, RadioGroup } from 'ant-design-vue'
import useUserStore from './useUserStore'
export default defineComponent(() => {
const router = useRouterStore()
const userStore = useUserStore()
const select = ref(1)
return () => (
<div class="fixed left-0 top-0 z-50 w-full">
<Transition>
<div
class="w-full h-screen bg-black/50"
></div>
</Transition>
<Transition name="modal">
<div class="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 overflow-hidden transition-all w-[400px] h-[240px] rounded-lg bg-white/30 ">
<div class="w-full h-full flex flex-col justify-between p-4 px-6 rounded-lg bg-white overflow-hidden relative">
<div class={"text-center border-b-[#ddd] border-b-[1px] pb-2 "}></div>
<span class={"text-[#666] text-[14px]"}></span>
<RadioGroup value={select.value} onChange={(e) => {
select.value = e.target.value
}} class={"flex flex-col text-[#333] gap-y-3"}>
<Radio value={1} class={"text-[#333]"}></Radio>
<Radio value={2} class={"text-[#333]"}></Radio>
</RadioGroup>
<div class={"flex justify-end "}
onClick={() => {
if (select.value === 1) {
userStore.comineData()
} else {
userStore.coverageData()
}
router.replace('')
}}
>
<button class={"px-10 py-1 hover:opacity-80 duration-150 bg-[#4a7aff] text-white rounded-lg"}></button>
</div>
</div>
</div>
</Transition>
</div>
)
})

View File

@ -39,12 +39,13 @@ export default defineComponent(() => {
</div>
<div class="flex py-2">
<div class={labelStyle}>:</div>
<Tag color={user.profile.gender === 1 ? 'blue' : 'red'}>
{user.profile.gender === 1 ? '男' : '女'}
<Tag color={user.profile.gender === 1 ? 'blue' : user.profile.gender === 2 ? 'red' : 'gray'}>
{user.profile.gender === 1 ? '男' : user.profile.gender === 2 ? '女' : '未知'}
</Tag>
</div>
</div>
)}
)
}
<div class="flex justify-around items-center my-10">
{user.isLogin ? (
@ -90,6 +91,6 @@ export default defineComponent(() => {
</Button>
)}
</div>
</div>
</div >
)
})

View File

@ -1,8 +1,9 @@
import type { Block, Layout } from '@/layout/layout.types'
import useLayoutStore from '@/layout/useLayoutStore'
import useRouterStore from '@/useRouterStore'
import request from '@/utils/request'
import { defineStore } from 'pinia'
import { computed, reactive, ref, watch } from 'vue'
import { computed, reactive, ref, toRefs, watch } from 'vue'
interface UserInfo {
id: string
@ -41,21 +42,55 @@ function getLinkList(data: Layout) {
}
return list
}
function areArraysEqualById(arr1: Block[], arr2: Block[]): boolean {
if (arr1.length !== arr2.length) {
return false;
}
// 将 arr2 转换为一个以 id 为键的映射
const arr2Map = new Map(arr2.map(item => [item.id, item]));
// 检查 arr1 中的每个 item 是否在 arr2 中存在,并且值是否相同
for (const item1 of arr1) {
const item2 = arr2Map.get(item1.id);
if (!item2 || JSON.stringify(item1) !== JSON.stringify(item2)) {
return false;
}
}
return true;
}
export default defineStore('user', () => {
const token = ref(localStorage.getItem('token') || '')
watch(token, (val) => {
localStorage.setItem('token', val)
})
const remoteData = ref<Layout | null>(null)
const remoteAddList = ref<Block[]>([])
const profile = reactive({ ...defaultUserInfo })
const layout = useLayoutStore()
const isLogin = computed(() => !!token.value && !!profile.id)
watch(
token,
async (val) => {
localStorage.setItem('token', val)
if (!val) return
const res = await request<UserInfo>('GET', '/api/profile')
Object.assign(profile, res)
},
{ immediate: true }
)
watch(
token,
async (val) => {
if (!val) return
const res = await request<UserInfo>('GET', '/api/profile')
Object.assign(profile, res)
console.log(val);
const data = await request<Layout>('GET', '/api/backup')
if (!data) return
const remoteList = getLinkList(data)
const localList = getLinkList(layout.state)
const addList: Block[] = []
@ -64,21 +99,37 @@ export default defineStore('user', () => {
addList.push(item)
}
}
if (addList.length > 0) {
if (addList.length > 0 || areArraysEqualById(remoteList, localList) || (remoteList.length !== localList.length)) {
// TODO: 交给张阳
remoteAddList.value = addList
remoteData.value = data
useRouterStore().go('global-backup')
}
},
{ immediate: true }
)
const isLogin = computed(() => !!token.value && !!profile.id)
const logout = () => {
token.value = ''
Object.assign(profile, { ...defaultUserInfo })
}
const comineData = () => {
if (!remoteData.value) return
Object.assign(layout.state.content[layout.state.currentPage].pages, remoteAddList.value)
}
const coverageData = () => {
if (!remoteData.value) return
console.log({ ...layout.state });
console.log({ ...remoteData.value });
Object.assign(layout.state, remoteData.value)
}
return {
token,
profile,
isLogin,
logout
logout,
coverageData,
comineData
}
})