Merge commit 'ea1bd25064bfd1e623c5f4bb9173e9112607484d' into tomato
This commit is contained in:
commit
3c2b441832
|
@ -7,7 +7,7 @@
|
||||||
name="viewport"
|
name="viewport"
|
||||||
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no"
|
||||||
/>
|
/>
|
||||||
<title>Vite App</title>
|
<title>Fatfox 新标签页</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="app"></div>
|
<div id="app"></div>
|
||||||
|
|
|
@ -25,7 +25,11 @@ export default defineComponent(() => {
|
||||||
full.value = false
|
full.value = false
|
||||||
})
|
})
|
||||||
return () => (
|
return () => (
|
||||||
<div class="fixed left-0 top-0 z-50 w-full">
|
<div
|
||||||
|
class="fixed left-0 top-0 z-50 w-full"
|
||||||
|
onContextmenu={(e) => e.stopPropagation()}
|
||||||
|
onKeydown={(e) => e.stopPropagation()}
|
||||||
|
>
|
||||||
{/* 背景遮罩 */}
|
{/* 背景遮罩 */}
|
||||||
<Transition>
|
<Transition>
|
||||||
{show.value && (
|
{show.value && (
|
||||||
|
|
|
@ -8,6 +8,7 @@ import { defineComponent, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||||
import useRouterStore from '@/useRouterStore'
|
import useRouterStore from '@/useRouterStore'
|
||||||
import useSearchStore from '@/layout/header/search/useSearchStore'
|
import useSearchStore from '@/layout/header/search/useSearchStore'
|
||||||
import useLayoutStore from '@/layout/useLayoutStore'
|
import useLayoutStore from '@/layout/useLayoutStore'
|
||||||
|
import { sendParent } from '@/utils/parent'
|
||||||
|
|
||||||
const stageStrList = [
|
const stageStrList = [
|
||||||
'dazhaohu',
|
'dazhaohu',
|
||||||
|
@ -128,6 +129,7 @@ export default defineComponent(() => {
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
run('aixin')
|
run('aixin')
|
||||||
|
sendParent(['openSide'])
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8" />
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
||||||
<title>Document</title>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div>要什么服务器,直接 oss</div>
|
|
||||||
<script src="/test.js" />
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -4,6 +4,9 @@ import type { Block } from './layout.types'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
import useLayoutStore from './useLayoutStore'
|
import useLayoutStore from './useLayoutStore'
|
||||||
import widgetList from '@/widgets'
|
import widgetList from '@/widgets'
|
||||||
|
import useRouterStore from '@/useRouterStore'
|
||||||
|
import useAdderPageStore from './adder/useAdderPageStore'
|
||||||
|
import useSettingsStore from '@/settings/useSettingsStore'
|
||||||
|
|
||||||
const defaultDisplay = {
|
const defaultDisplay = {
|
||||||
x: 0,
|
x: 0,
|
||||||
|
@ -26,8 +29,8 @@ export const useMenuStore = defineStore('menu', () => {
|
||||||
window.removeEventListener('mousemove', handle)
|
window.removeEventListener('mousemove', handle)
|
||||||
})
|
})
|
||||||
const open = (type: (typeof defaultDisplay)['type']) => {
|
const open = (type: (typeof defaultDisplay)['type']) => {
|
||||||
display.x = Math.min(window.innerWidth - 140, mPos.x)
|
display.x = Math.min(window.innerWidth - 180, mPos.x)
|
||||||
display.y = Math.min(window.innerHeight - 240, mPos.y)
|
display.y = Math.min(window.innerHeight - 220, mPos.y)
|
||||||
display.type = type
|
display.type = type
|
||||||
}
|
}
|
||||||
const show = computed(() => display.x > 0 && display.y > 0)
|
const show = computed(() => display.x > 0 && display.y > 0)
|
||||||
|
@ -49,6 +52,10 @@ const Item = defineComponent({
|
||||||
alert: {
|
alert: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false
|
default: false
|
||||||
|
},
|
||||||
|
noStyle: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
emits: {
|
emits: {
|
||||||
|
@ -61,9 +68,17 @@ const Item = defineComponent({
|
||||||
'px-4 py-2 text-sm tracking-widest w-full overflow-hidden text-ellipsis whitespace-nowrap break-all transition-all rounded-lg cursor-pointer mb-2',
|
'px-4 py-2 text-sm tracking-widest w-full overflow-hidden text-ellipsis whitespace-nowrap break-all transition-all rounded-lg cursor-pointer mb-2',
|
||||||
{
|
{
|
||||||
'bg-red-500/80 hover:bg-red-500 text-white': props.alert,
|
'bg-red-500/80 hover:bg-red-500 text-white': props.alert,
|
||||||
'bg-white/80 hover:bg-white text-black/80': !props.alert
|
'bg-white/80 hover:bg-white text-black/80': !props.alert && !props.noStyle,
|
||||||
|
'bg-transparent text-black/60 hover:text-black/80 hover:bg-white/20': props.noStyle
|
||||||
}
|
}
|
||||||
)}
|
)}
|
||||||
|
style={
|
||||||
|
props.noStyle
|
||||||
|
? {
|
||||||
|
padding: '6px 10px'
|
||||||
|
}
|
||||||
|
: {}
|
||||||
|
}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
ctx.emit('click')
|
ctx.emit('click')
|
||||||
}}
|
}}
|
||||||
|
@ -76,28 +91,98 @@ const Item = defineComponent({
|
||||||
|
|
||||||
export default defineComponent(() => {
|
export default defineComponent(() => {
|
||||||
const menu = useMenuStore()
|
const menu = useMenuStore()
|
||||||
|
const settings = useSettingsStore()
|
||||||
const layout = useLayoutStore()
|
const layout = useLayoutStore()
|
||||||
|
document.addEventListener('contextmenu', () => {
|
||||||
|
menu.open('global')
|
||||||
|
})
|
||||||
|
const router = useRouterStore()
|
||||||
|
const adderPage = useAdderPageStore()
|
||||||
return () =>
|
return () =>
|
||||||
menu.show && (
|
menu.show && (
|
||||||
<div
|
<div
|
||||||
v-outside-click={() => {
|
v-outside-click={() => {
|
||||||
menu.dismiss()
|
menu.dismiss()
|
||||||
}}
|
}}
|
||||||
class="fixed px-2 pt-4 pb-2 bg-white/60 backdrop-blur shadow-lg rounded-lg overflow-hidden w-[120px]"
|
class="fixed px-2 pt-4 pb-2 bg-white/60 backdrop-blur shadow-lg rounded-lg overflow-hidden"
|
||||||
style={{
|
style={{
|
||||||
zIndex: '999',
|
zIndex: '999',
|
||||||
left: menu.display.x + 'px',
|
left: menu.display.x + 'px',
|
||||||
top: menu.display.y + 'px'
|
top: menu.display.y + 'px',
|
||||||
|
width: menu.display.type === 'global' ? '160px' : '120px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{(() => {
|
{(() => {
|
||||||
if (menu.display.type === 'global') {
|
if (menu.display.type === 'global') {
|
||||||
// 全局菜单
|
// 全局菜单
|
||||||
return <></>
|
return (
|
||||||
|
<>
|
||||||
|
<Item
|
||||||
|
noStyle
|
||||||
|
onClick={() => {
|
||||||
|
router.go('global-adder')
|
||||||
|
adderPage.type = 1
|
||||||
|
menu.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加网址导航
|
||||||
|
</Item>
|
||||||
|
<Item
|
||||||
|
noStyle
|
||||||
|
onClick={() => {
|
||||||
|
router.go('global-adder')
|
||||||
|
adderPage.type = 0
|
||||||
|
menu.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加功能组件
|
||||||
|
</Item>
|
||||||
|
<Item
|
||||||
|
noStyle
|
||||||
|
onClick={() => {
|
||||||
|
router.go('global-adder')
|
||||||
|
adderPage.type = 3
|
||||||
|
menu.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加快游戏
|
||||||
|
</Item>
|
||||||
|
<Item
|
||||||
|
noStyle
|
||||||
|
onClick={() => {
|
||||||
|
router.go('global-background')
|
||||||
|
menu.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
更换壁纸
|
||||||
|
</Item>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
if (menu.display.type === 'dock') {
|
if (menu.display.type === 'dock') {
|
||||||
// dock 栏
|
// dock 栏
|
||||||
return <></>
|
return (
|
||||||
|
<>
|
||||||
|
<Item
|
||||||
|
noStyle
|
||||||
|
onClick={() => {
|
||||||
|
settings.state.disabledShortcut = !settings.state.disabledShortcut
|
||||||
|
menu.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{settings.state.disabledShortcut ? '启用' : '禁用'}快捷键
|
||||||
|
</Item>
|
||||||
|
<Item
|
||||||
|
noStyle
|
||||||
|
onClick={() => {
|
||||||
|
router.go('settings-dock')
|
||||||
|
menu.dismiss()
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
编辑快捷键
|
||||||
|
</Item>
|
||||||
|
</>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
const block = menu.display.type
|
const block = menu.display.type
|
||||||
if (!block.link) {
|
if (!block.link) {
|
||||||
|
@ -190,7 +275,7 @@ export default defineComponent(() => {
|
||||||
// 链接
|
// 链接
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Item>测试</Item>
|
<Item>编辑</Item>
|
||||||
<Item
|
<Item
|
||||||
alert
|
alert
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
import { computed, defineComponent, inject, onMounted, onUnmounted, provide, ref, type InjectionKey, type Ref } from 'vue'
|
import {
|
||||||
|
computed,
|
||||||
|
defineComponent,
|
||||||
|
onUnmounted,
|
||||||
|
provide,
|
||||||
|
ref,
|
||||||
|
type InjectionKey,
|
||||||
|
type Ref
|
||||||
|
} from 'vue'
|
||||||
import useLayoutStore from '../useLayoutStore'
|
import useLayoutStore from '../useLayoutStore'
|
||||||
import { OhVueIcon, addIcons } from 'oh-vue-icons'
|
import { OhVueIcon, addIcons } from 'oh-vue-icons'
|
||||||
import {
|
import {
|
||||||
|
@ -74,7 +82,7 @@ export default defineComponent(() => {
|
||||||
const store = useAdderPageStore()
|
const store = useAdderPageStore()
|
||||||
const addTo = ref(layout.state.currentPage)
|
const addTo = ref(layout.state.currentPage)
|
||||||
provide(AddToToken, addTo)
|
provide(AddToToken, addTo)
|
||||||
onUnmounted(()=> {
|
onUnmounted(() => {
|
||||||
store.type = 1
|
store.type = 1
|
||||||
})
|
})
|
||||||
return () => (
|
return () => (
|
||||||
|
@ -124,10 +132,7 @@ export default defineComponent(() => {
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class={'w-0 h-full flex-grow relative z-10 flex flex-col ' + (isGame.value ? '' : '')}>
|
||||||
class={'w-0 h-full flex-grow relative z-10 flex flex-col ' + (isGame.value ? '' : '')}
|
|
||||||
onContextmenu={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<Form class="w-full px-4 mt-4" layout="inline">
|
<Form class="w-full px-4 mt-4" layout="inline">
|
||||||
<Form.Item label="添加到">
|
<Form.Item label="添加到">
|
||||||
<Select
|
<Select
|
||||||
|
@ -147,7 +152,7 @@ export default defineComponent(() => {
|
||||||
<div class="w-full h-full relative">
|
<div class="w-full h-full relative">
|
||||||
{store.type === 0 ? (
|
{store.type === 0 ? (
|
||||||
<WidgetAdder />
|
<WidgetAdder />
|
||||||
) : store.type=== 1 ? (
|
) : store.type === 1 ? (
|
||||||
<HotAdder />
|
<HotAdder />
|
||||||
) : store.type === 2 ? (
|
) : store.type === 2 ? (
|
||||||
<CustomAdder />
|
<CustomAdder />
|
||||||
|
|
|
@ -4,6 +4,7 @@ import useSortable, { dragging, resetDragging } from '../grid/useSortable'
|
||||||
import LinkBlock from '../grid/LinkBlock'
|
import LinkBlock from '../grid/LinkBlock'
|
||||||
import useSettingsStore from '@/settings/useSettingsStore'
|
import useSettingsStore from '@/settings/useSettingsStore'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
import { useMenuStore } from '../GlobalMenu'
|
||||||
|
|
||||||
export default defineComponent(() => {
|
export default defineComponent(() => {
|
||||||
const layout = useLayoutStore()
|
const layout = useLayoutStore()
|
||||||
|
@ -13,11 +14,12 @@ export default defineComponent(() => {
|
||||||
computed(() => layout.state.dock),
|
computed(() => layout.state.dock),
|
||||||
ref('dock')
|
ref('dock')
|
||||||
)
|
)
|
||||||
|
const menu = useMenuStore()
|
||||||
const current = ref(-1)
|
const current = ref(-1)
|
||||||
return () =>
|
return () =>
|
||||||
setting.state.showDock !== '' && (
|
setting.state.showDock !== '' && (
|
||||||
<div
|
<div
|
||||||
onDragover={()=> {
|
onDragover={() => {
|
||||||
show.value = true
|
show.value = true
|
||||||
}}
|
}}
|
||||||
onMouseenter={() => {
|
onMouseenter={() => {
|
||||||
|
@ -26,9 +28,7 @@ export default defineComponent(() => {
|
||||||
onMouseleave={() => {
|
onMouseleave={() => {
|
||||||
show.value = false
|
show.value = false
|
||||||
}}
|
}}
|
||||||
class={
|
class={'w-3/5 min-w-[800px] h-[120px] fixed left-1/2 bottom-0 -translate-x-1/2'}
|
||||||
'w-3/5 min-w-[800px] h-[120px] fixed left-1/2 bottom-0 -translate-x-1/2'
|
|
||||||
}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class={clsx(
|
class={clsx(
|
||||||
|
@ -43,6 +43,11 @@ export default defineComponent(() => {
|
||||||
onMouseleave={() => {
|
onMouseleave={() => {
|
||||||
current.value = -1
|
current.value = -1
|
||||||
}}
|
}}
|
||||||
|
onContextmenu={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
menu.open('dock')
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{layout.state.dockLabels.split('').map((l, i) => {
|
{layout.state.dockLabels.split('').map((l, i) => {
|
||||||
const block = layout.state.dock[i]
|
const block = layout.state.dock[i]
|
||||||
|
@ -87,12 +92,14 @@ export default defineComponent(() => {
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{block && <LinkBlock block={block} dock />}
|
{block && <LinkBlock block={block} dock />}
|
||||||
<div
|
{!setting.state.disabledShortcut && (
|
||||||
class="absolute z-10 left-0 bottom-0 w-full bg-black/20 text-[12px] text-white text-center"
|
<div
|
||||||
style={{ boxShadow: block ? 'none' : '0 -4px 14px 0 rgba(0,0,0,.3)' }}
|
class="absolute z-10 left-0 bottom-0 w-full bg-black/20 text-[12px] text-white text-center"
|
||||||
>
|
style={{ boxShadow: block ? 'none' : '0 -4px 14px 0 rgba(0,0,0,.3)' }}
|
||||||
{l}
|
>
|
||||||
</div>
|
{l}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
|
|
|
@ -120,6 +120,10 @@ export default defineComponent({
|
||||||
style={{
|
style={{
|
||||||
borderRadius: `calc(var(--block-radius) * var(--block-size))`
|
borderRadius: `calc(var(--block-radius) * var(--block-size))`
|
||||||
}}
|
}}
|
||||||
|
onContextmenu={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{props.block.link ? (
|
{props.block.link ? (
|
||||||
props.block.link.startsWith('id:') ? (
|
props.block.link.startsWith('id:') ? (
|
||||||
|
|
|
@ -39,9 +39,8 @@ export default defineComponent({
|
||||||
'grid-rows-3 grid-cols-3 gap-[6%] p-[8%]': props.big,
|
'grid-rows-3 grid-cols-3 gap-[6%] p-[8%]': props.big,
|
||||||
'grid-rows-2 grid-cols-2 gap-[8%] p-[10%]': !props.big
|
'grid-rows-2 grid-cols-2 gap-[8%] p-[10%]': !props.big
|
||||||
})}
|
})}
|
||||||
onContextmenu={(e) => {
|
onContextmenu={() => {
|
||||||
e.preventDefault()
|
menu.open('dock')
|
||||||
menu.open(props.block)
|
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedDir.value.list
|
{selectedDir.value.list
|
||||||
|
|
|
@ -37,8 +37,15 @@ export default defineComponent(() => {
|
||||||
<input
|
<input
|
||||||
class="relative h-[40px] mb-2 w-[240px] bg-transparent outline-none border-none text-center text-white"
|
class="relative h-[40px] mb-2 w-[240px] bg-transparent outline-none border-none text-center text-white"
|
||||||
v-model={dir.value.label}
|
v-model={dir.value.label}
|
||||||
|
onKeydown={(e) => e.stopPropagation()}
|
||||||
/>
|
/>
|
||||||
<div class="relative w-[50%] min-h-[280px] max-h-[60vh] overflow-y-auto bg-white/60 backdrop-blur rounded-lg shadow-lg p-2">
|
<div
|
||||||
|
class="relative w-[50%] min-h-[280px] max-h-[60vh] overflow-y-auto bg-white/60 backdrop-blur rounded-lg shadow-lg p-2"
|
||||||
|
onContextmenu={(e) => {
|
||||||
|
e.stopPropagation()
|
||||||
|
e.preventDefault()
|
||||||
|
}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="w-full grid justify-center grid-flow-row-dense pb-[200px]"
|
class="w-full grid justify-center grid-flow-row-dense pb-[200px]"
|
||||||
style="grid-template-columns:repeat(auto-fill, var(--block-size));grid-auto-rows:var(--block-size)"
|
style="grid-template-columns:repeat(auto-fill, var(--block-size));grid-auto-rows:var(--block-size)"
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { defineComponent } from 'vue'
|
import { defineComponent } from 'vue'
|
||||||
import type { Block } from '../layout.types'
|
import type { Block } from '../layout.types'
|
||||||
import { useMenuStore } from '../GlobalMenu'
|
import { useMenuStore } from '../GlobalMenu'
|
||||||
|
import jump from '@/utils/jump'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
props: {
|
props: {
|
||||||
|
@ -23,12 +24,11 @@ export default defineComponent({
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
class="w-full h-full flex justify-center items-center font-bold bg-cover bg-center bg-no-repeat"
|
class="w-full h-full flex justify-center items-center font-bold bg-cover bg-center bg-no-repeat"
|
||||||
onContextmenu={(e) => {
|
onContextmenu={() => {
|
||||||
e.preventDefault()
|
|
||||||
menu.open(props.block)
|
menu.open(props.block)
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
window.open(props.block.link, '_blank')
|
jump(props.block.link)
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
backgroundColor: props.block.background || 'white',
|
backgroundColor: props.block.background || 'white',
|
||||||
|
@ -44,8 +44,7 @@ export default defineComponent({
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div
|
||||||
class="w-full h-full flex justify-between px-3 items-center font-bold bg-cover bg-center bg-no-repeat"
|
class="w-full h-full flex justify-between px-3 items-center font-bold bg-cover bg-center bg-no-repeat"
|
||||||
onContextmenu={(e) => {
|
onContextmenu={() => {
|
||||||
e.preventDefault()
|
|
||||||
menu.open(props.block)
|
menu.open(props.block)
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
@ -61,7 +60,11 @@ export default defineComponent({
|
||||||
{props.block.label}
|
{props.block.label}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<img src="/tab/icons/gameicon.webp" alt="game_icon" class={'absolute right-0 bottom-0 w-[36px]'} />
|
<img
|
||||||
|
src="/tab/icons/gameicon.webp"
|
||||||
|
alt="game_icon"
|
||||||
|
class={'absolute right-0 bottom-0 w-[36px]'}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import DivBgImg from '~/icons/welcome/back.png'
|
||||||
import startUseImg from '~/icons/welcome/startUse.png'
|
import startUseImg from '~/icons/welcome/startUse.png'
|
||||||
import useBackgroundStore from '../background/useBackgroundStore'
|
import useBackgroundStore from '../background/useBackgroundStore'
|
||||||
import useLayoutStore from '../useLayoutStore'
|
import useLayoutStore from '../useLayoutStore'
|
||||||
|
import request from '@/utils/request'
|
||||||
export const DefaultPageSetting = [
|
export const DefaultPageSetting = [
|
||||||
{
|
{
|
||||||
name: '游戏',
|
name: '游戏',
|
||||||
|
@ -43,7 +44,6 @@ export default defineComponent(() => {
|
||||||
if (!visited) {
|
if (!visited) {
|
||||||
// 如果没有记录,说明是第一次访问
|
// 如果没有记录,说明是第一次访问
|
||||||
isFirst.value = true
|
isFirst.value = true
|
||||||
// 设置标记,后续访问不会再次显示
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
return () =>
|
return () =>
|
||||||
|
@ -123,7 +123,14 @@ export default defineComponent(() => {
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
localStorage.setItem('hasVisited', 'true')
|
localStorage.setItem('hasVisited', 'true')
|
||||||
isFirst.value = false
|
isFirst.value = false
|
||||||
layout.changeBackground(DefaultPageSetting[selectMode.value].backgroundUrl)
|
|
||||||
|
// 设置标记,后续访问不会再次显示
|
||||||
|
// 获取默认界面
|
||||||
|
request('GET', '/api/app/desktop').then((res: any) => {
|
||||||
|
if (!res) return
|
||||||
|
layout.state.dir = res.dir
|
||||||
|
layout.state.content = res.content
|
||||||
|
})
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
backgroundImage: `url('${startUseImg}')`,
|
backgroundImage: `url('${startUseImg}')`,
|
||||||
|
|
|
@ -16,10 +16,14 @@ export default defineComponent({
|
||||||
const router = useRouterStore()
|
const router = useRouterStore()
|
||||||
return () => {
|
return () => {
|
||||||
const placeholder = (
|
const placeholder = (
|
||||||
<div class="w-full h-full flex justify-center items-center text-black/60" onContextmenu={(e) => {
|
<div
|
||||||
e.preventDefault()
|
class="w-full h-full flex justify-center items-center text-black/60"
|
||||||
menu.open(props.block)
|
onContextmenu={() => {
|
||||||
}}>组件维护中</div>
|
menu.open(props.block)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
组件维护中
|
||||||
|
</div>
|
||||||
)
|
)
|
||||||
const selected = widgetList.find((el) => el.name === props.block.name)
|
const selected = widgetList.find((el) => el.name === props.block.name)
|
||||||
if (!selected) return placeholder
|
if (!selected) return placeholder
|
||||||
|
@ -30,8 +34,7 @@ export default defineComponent({
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
class="w-full h-full relative"
|
class="w-full h-full relative"
|
||||||
onContextmenu={(e) => {
|
onContextmenu={() => {
|
||||||
e.preventDefault()
|
|
||||||
menu.open(props.block)
|
menu.open(props.block)
|
||||||
}}
|
}}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
|
|
|
@ -116,10 +116,7 @@ export default defineComponent(() => {
|
||||||
const searchConfig = useSearchConfigStore()
|
const searchConfig = useSearchConfigStore()
|
||||||
const showAdder = ref<{ [key: string]: any } | null | undefined>(undefined)
|
const showAdder = ref<{ [key: string]: any } | null | undefined>(undefined)
|
||||||
return () => (
|
return () => (
|
||||||
<div
|
<div class="w-full h-full bg-white/80 backdrop-blur p-4 flex flex-col select-text">
|
||||||
class="w-full h-full bg-white/80 backdrop-blur p-4 flex flex-col select-text"
|
|
||||||
onContextmenu={(e) => e.stopPropagation()}
|
|
||||||
>
|
|
||||||
<ThemeProvider>
|
<ThemeProvider>
|
||||||
<h2 class="text-center tracking-widest font-bold text-xl text-black/80">管理搜索引擎</h2>
|
<h2 class="text-center tracking-widest font-bold text-xl text-black/80">管理搜索引擎</h2>
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
|
|
|
@ -8,68 +8,73 @@ import SearchSuggestion from './SearchSuggestion'
|
||||||
import useLayoutStore from '@/layout/useLayoutStore'
|
import useLayoutStore from '@/layout/useLayoutStore'
|
||||||
import clsx from 'clsx'
|
import clsx from 'clsx'
|
||||||
|
|
||||||
export default defineComponent((props: {
|
export default defineComponent(
|
||||||
isMini?: boolean
|
(props: { isMini?: boolean }) => {
|
||||||
}) => {
|
const settings = useSettingsStore()
|
||||||
const settings = useSettingsStore()
|
const search = useSearchStore()
|
||||||
const search = useSearchStore()
|
const searchConfig = useSearchConfigStore()
|
||||||
const searchConfig = useSearchConfigStore()
|
const layout = useLayoutStore()
|
||||||
const layout = useLayoutStore()
|
return () => (
|
||||||
return () => (
|
|
||||||
<div
|
|
||||||
class={clsx(!props?.isMini ? "absolute left-1/2 -translate-x-1/2 z-20 transition-all" : "w-full")}
|
|
||||||
style={
|
|
||||||
props.isMini ? {
|
|
||||||
|
|
||||||
} :
|
|
||||||
{
|
|
||||||
top: layout.isCompact ? '40px' : layout.state.simple ? '230px' : '172px',
|
|
||||||
width: settings.state.searchWidth + 'rem'
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<div
|
<div
|
||||||
class={
|
class={clsx(
|
||||||
clsx(
|
!props?.isMini ? 'absolute left-1/2 -translate-x-1/2 z-20 transition-all' : 'w-full'
|
||||||
'w-full h-11 shadow-content overflow-hidden px-1 transition-all flex justify-between items-center gap-4 ',
|
)}
|
||||||
(search.focus ? 'bg-white/60' : 'bg-white/40 hover:bg-white/60'),
|
style={
|
||||||
props.isMini ? "" : "max-w-[90vw] w-full")
|
props.isMini
|
||||||
|
? {}
|
||||||
|
: {
|
||||||
|
top: layout.isCompact ? '40px' : layout.state.simple ? '230px' : '172px',
|
||||||
|
width: settings.state.searchWidth + 'rem'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
style={{
|
|
||||||
borderRadius: settings.state.searchRadius + 'px'
|
|
||||||
}}
|
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="w-9 h-11 flex justify-center items-center cursor-pointer"
|
class={clsx(
|
||||||
onClick={() => {
|
'w-full h-11 shadow-content overflow-hidden px-1 transition-all flex justify-between items-center gap-4 ',
|
||||||
search.showSearchConfig = true
|
search.focus ? 'bg-white/60' : 'bg-white/40 hover:bg-white/60',
|
||||||
|
props.isMini ? '' : 'max-w-[90vw] w-full'
|
||||||
|
)}
|
||||||
|
style={{
|
||||||
|
borderRadius: settings.state.searchRadius + 'px'
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="w-[26px] h-[26px] bg-center bg-contain bg-no-repeat"
|
class="w-9 h-11 flex justify-center items-center cursor-pointer"
|
||||||
style={{
|
onClick={() => {
|
||||||
backgroundImage: `url('${searchConfig.current.icon}')`,
|
search.showSearchConfig = true
|
||||||
borderRadius: settings.state.searchRadius - 4 + 'px'
|
|
||||||
}}
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="w-[26px] h-[26px] bg-center bg-contain bg-no-repeat"
|
||||||
|
style={{
|
||||||
|
backgroundImage: `url('${searchConfig.current.icon}')`,
|
||||||
|
borderRadius: settings.state.searchRadius - 4 + 'px'
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<input
|
||||||
|
v-model={search.searchStr}
|
||||||
|
ref={(el) => (search.searchRef = el as any)}
|
||||||
|
onContextmenu={(e) => e.stopPropagation()}
|
||||||
|
onKeydown={(e) => e.stopPropagation()}
|
||||||
|
class="flex-1 h-full outline-none bg-transparent placeholder:text-slate-600 placeholder:tracking-widest text-slate-800 pr-4"
|
||||||
|
placeholder={`输入搜索 ${searchConfig.current.name}`}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<input
|
<Transition name="searchContent">{search.showSearchConfig && <SearchConfig />}</Transition>
|
||||||
v-model={search.searchStr}
|
<Transition name="searchContent">
|
||||||
ref={(el) => (search.searchRef = el as any)}
|
{search.focus && !search.searchStr && searchConfig.history.length > 0 && (
|
||||||
onContextmenu={(e) => e.stopPropagation()}
|
<SearchHistory />
|
||||||
class="flex-1 h-full outline-none bg-transparent placeholder:text-slate-600 placeholder:tracking-widest text-slate-800 pr-4"
|
)}
|
||||||
placeholder={`输入搜索 ${searchConfig.current.name}`}
|
</Transition>
|
||||||
/>
|
<Transition name="searchContent">
|
||||||
|
{search.focus && search.searchStr && <SearchSuggestion />}
|
||||||
|
</Transition>
|
||||||
</div>
|
</div>
|
||||||
<Transition name="searchContent">{search.showSearchConfig && <SearchConfig />}</Transition>
|
)
|
||||||
<Transition name="searchContent">
|
},
|
||||||
{search.focus && !search.searchStr && searchConfig.history.length > 0 && <SearchHistory />}
|
{
|
||||||
</Transition>
|
name: 'SearchComponent',
|
||||||
<Transition name="searchContent">
|
props: ['isMini']
|
||||||
{search.focus && search.searchStr && <SearchSuggestion />}
|
}
|
||||||
</Transition>
|
)
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}, {
|
|
||||||
name: 'SearchComponent',
|
|
||||||
props: ['isMini']
|
|
||||||
})
|
|
||||||
|
|
|
@ -4,6 +4,8 @@ import { computed, reactive, ref, toRaw, watch } from 'vue'
|
||||||
import db from '@/db'
|
import db from '@/db'
|
||||||
import useResource from './background/useResource'
|
import useResource from './background/useResource'
|
||||||
import { globalToast } from '@/main'
|
import { globalToast } from '@/main'
|
||||||
|
import jump from '@/utils/jump'
|
||||||
|
import useSettingsStore from '@/settings/useSettingsStore'
|
||||||
|
|
||||||
const defaultLayout: Layout = {
|
const defaultLayout: Layout = {
|
||||||
content: [
|
content: [
|
||||||
|
@ -20,6 +22,7 @@ const defaultLayout: Layout = {
|
||||||
}
|
}
|
||||||
|
|
||||||
export default defineStore('layout', () => {
|
export default defineStore('layout', () => {
|
||||||
|
const settings = useSettingsStore()
|
||||||
const state = reactive(defaultLayout)
|
const state = reactive(defaultLayout)
|
||||||
const ready = ref(false)
|
const ready = ref(false)
|
||||||
|
|
||||||
|
@ -86,6 +89,12 @@ export default defineStore('layout', () => {
|
||||||
if (openDir.value === id) {
|
if (openDir.value === id) {
|
||||||
openDir.value = ''
|
openDir.value = ''
|
||||||
}
|
}
|
||||||
|
} else if (dir && dir.list.length === 0) {
|
||||||
|
const idx = currentPage.value.list.findIndex((el) => el.link === 'id:' + id)
|
||||||
|
if (idx < 0) return
|
||||||
|
currentPage.value.list.splice(idx, 1)
|
||||||
|
delete state.dir[id]
|
||||||
|
openDir.value = ''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,7 +105,6 @@ export default defineStore('layout', () => {
|
||||||
}
|
}
|
||||||
// 处理不同的组件的名称
|
// 处理不同的组件的名称
|
||||||
if (block.name === 'gameVideo') {
|
if (block.name === 'gameVideo') {
|
||||||
|
|
||||||
return state.current === 0 ? '游戏视频' : state.current === 1 ? '学习视频' : '娱乐视频'
|
return state.current === 0 ? '游戏视频' : state.current === 1 ? '学习视频' : '娱乐视频'
|
||||||
}
|
}
|
||||||
return block.label || ''
|
return block.label || ''
|
||||||
|
@ -105,6 +113,18 @@ export default defineStore('layout', () => {
|
||||||
const changeBackground = (url: string) => {
|
const changeBackground = (url: string) => {
|
||||||
state.content[state.current].background = url
|
state.content[state.current].background = url
|
||||||
}
|
}
|
||||||
|
document.addEventListener('keydown', (e) => {
|
||||||
|
if (settings.state.disabledShortcut) return
|
||||||
|
const arr = state.dockLabels.split('')
|
||||||
|
for (const key in arr) {
|
||||||
|
if (arr[key] === e.key.toLocaleUpperCase()) {
|
||||||
|
const block = state.dock[key]
|
||||||
|
if (block) {
|
||||||
|
jump(block.link)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
return {
|
return {
|
||||||
state,
|
state,
|
||||||
ready,
|
ready,
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { defineStore } from 'pinia'
|
||||||
import { computed, reactive } from 'vue'
|
import { computed, reactive } from 'vue'
|
||||||
|
|
||||||
export type VisibleState = 'show' | 'auto' | ''
|
export type VisibleState = 'show' | 'auto' | ''
|
||||||
export type TimeUnit = 'date' | 'week' | '12hour' | 'lunal' | 'second';
|
export type TimeUnit = 'date' | 'week' | '12hour' | 'lunal' | 'second'
|
||||||
export default defineStore(
|
export default defineStore(
|
||||||
'settings',
|
'settings',
|
||||||
() => {
|
() => {
|
||||||
|
@ -32,7 +32,8 @@ export default defineStore(
|
||||||
searchOpacity: 0.75,
|
searchOpacity: 0.75,
|
||||||
// 侧边栏
|
// 侧边栏
|
||||||
siderDirection: 'left' as 'left' | 'right',
|
siderDirection: 'left' as 'left' | 'right',
|
||||||
|
// 禁用快捷键
|
||||||
|
disabledShortcut: false
|
||||||
})
|
})
|
||||||
return { state, blockInner: computed(() => state.blockSize - 2 * state.blockPadding) }
|
return { state, blockInner: computed(() => state.blockSize - 2 * state.blockPadding) }
|
||||||
},
|
},
|
||||||
|
|
|
@ -30,7 +30,6 @@ export default defineStore('user', () => {
|
||||||
if (!val) return
|
if (!val) return
|
||||||
request<UserInfo>('GET', '/api/profile').then((res) => {
|
request<UserInfo>('GET', '/api/profile').then((res) => {
|
||||||
Object.assign(profile, res)
|
Object.assign(profile, res)
|
||||||
|
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
{ immediate: true }
|
{ immediate: true }
|
||||||
|
@ -41,6 +40,7 @@ export default defineStore('user', () => {
|
||||||
Object.assign(profile, {...defaultUserInfo})
|
Object.assign(profile, {...defaultUserInfo})
|
||||||
// profile.avatar = ''
|
// profile.avatar = ''
|
||||||
}
|
}
|
||||||
|
// 自动备份
|
||||||
return {
|
return {
|
||||||
token,
|
token,
|
||||||
profile,
|
profile,
|
||||||
|
|
|
@ -1,25 +1,20 @@
|
||||||
import db from '@/db'
|
import db from '@/db'
|
||||||
|
import request from './request'
|
||||||
|
|
||||||
interface AdverLink {
|
type AdverContent = { id: string; tag: string; content: string }
|
||||||
id: string
|
|
||||||
tag: string
|
|
||||||
adverLink: string
|
|
||||||
}
|
|
||||||
type AdverParams = Omit<AdverLink, 'adverLink'> & {
|
|
||||||
adverParams: string
|
|
||||||
}
|
|
||||||
|
|
||||||
type AdverData = {
|
type AdverData = {
|
||||||
links: AdverLink[]
|
links: AdverContent[]
|
||||||
params: AdverParams[]
|
params: AdverContent[]
|
||||||
expiration: number
|
expiration: number
|
||||||
}
|
}
|
||||||
|
|
||||||
const fetchAdverConfig = async () => {
|
const fetchAdverConfig = async () => {
|
||||||
return Promise.allSettled([
|
return Promise.allSettled([
|
||||||
fetch('https://api.iyuntab.com/adverLink/params').then((res) => res.json()),
|
request('GET', '/api/app/adverLinks/params'),
|
||||||
fetch('https://api.iyuntab.com/adverLink/link').then((res) => res.json())
|
request('GET', '/api/app/adverLinks/link')
|
||||||
]).then((res) => {
|
]).then((res: any) => {
|
||||||
|
console.log('----', res)
|
||||||
const result: AdverData = { links: [], params: [], expiration: Date.now() + 1000 * 60 * 60 * 4 }
|
const result: AdverData = { links: [], params: [], expiration: Date.now() + 1000 * 60 * 60 * 4 }
|
||||||
if (res[0].status === 'fulfilled') {
|
if (res[0].status === 'fulfilled') {
|
||||||
result.params = res[0].value
|
result.params = res[0].value
|
||||||
|
@ -31,14 +26,12 @@ const fetchAdverConfig = async () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
export function getAdverConfig() {
|
export function getAdverConfig() {
|
||||||
return db
|
return db.getItem<AdverData>('adverInfo').then((res) => {
|
||||||
.getItem<{ links: AdverLink[]; params: AdverParams[]; expiration: number }>('adverInfo')
|
if (!res || res.expiration < Date.now()) {
|
||||||
.then((res) => {
|
return fetchAdverConfig()
|
||||||
if (!res || res.expiration < Date.now()) {
|
}
|
||||||
return fetchAdverConfig()
|
return Promise.resolve(res)
|
||||||
}
|
})
|
||||||
return Promise.resolve(res)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function checkWithAdver(_url: string) {
|
async function checkWithAdver(_url: string) {
|
||||||
|
@ -47,7 +40,7 @@ async function checkWithAdver(_url: string) {
|
||||||
const tag = _url.match(/(?<=http(s?):\/\/).*/g)?.[0] || _url
|
const tag = _url.match(/(?<=http(s?):\/\/).*/g)?.[0] || _url
|
||||||
for (const item of config.params) {
|
for (const item of config.params) {
|
||||||
if (tag.startsWith(item.tag)) {
|
if (tag.startsWith(item.tag)) {
|
||||||
const params = new URLSearchParams(item.adverParams)
|
const params = new URLSearchParams(item.content)
|
||||||
const origin = new URLSearchParams(_url.includes('?') ? _url : _url + '?')
|
const origin = new URLSearchParams(_url.includes('?') ? _url : _url + '?')
|
||||||
for (const key of params.keys()) {
|
for (const key of params.keys()) {
|
||||||
const value = params.get(key)
|
const value = params.get(key)
|
||||||
|
@ -59,8 +52,8 @@ async function checkWithAdver(_url: string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const item of config.links) {
|
for (const item of config.links) {
|
||||||
if (item.tag.startsWith(tag)) {
|
if (_url.startsWith(item.tag)) {
|
||||||
return item.adverLink
|
return item.content
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return _url
|
return _url
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
// 发送消息
|
||||||
|
export function sendParent(data: ['openSide']) {
|
||||||
|
parent.window.postMessage(
|
||||||
|
{
|
||||||
|
type: data[0],
|
||||||
|
data: (data as any)[1]
|
||||||
|
},
|
||||||
|
'*'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收消息
|
||||||
|
export function listenParent<T>(type: string, cb: (data: T) => void) {
|
||||||
|
window.addEventListener('message', (e) => {
|
||||||
|
if (e.data?.type === 'uitab-' + type) {
|
||||||
|
cb(e.data.data)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ import asyncLoader from '@/utils/asyncLoader'
|
||||||
import type { Widget } from '..'
|
import type { Widget } from '..'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'gameNews',
|
name: 'gamePlay',
|
||||||
label: '经典即玩游戏',
|
label: '经典即玩游戏',
|
||||||
description: '经典即玩游戏',
|
description: '经典即玩游戏',
|
||||||
icon: '/tab/icons/classicPlay.png',
|
icon: '/tab/icons/classicPlay.png',
|
||||||
|
|
Loading…
Reference in New Issue