316 lines
9.2 KiB
TypeScript
316 lines
9.2 KiB
TypeScript
import { defineStore } from 'pinia'
|
|
import { computed, defineComponent, onUnmounted, reactive } from 'vue'
|
|
import type { Block } from './layout.types'
|
|
import clsx from 'clsx'
|
|
import useLayoutStore from './useLayoutStore'
|
|
import widgetList from '@/widgets'
|
|
import useRouterStore from '@/useRouterStore'
|
|
import useAdderPageStore from './adder/useAdderPageStore'
|
|
import useSettingsStore from '@/settings/useSettingsStore'
|
|
|
|
const defaultDisplay = {
|
|
x: 0,
|
|
y: 0,
|
|
type: 'global' as Block | 'global' | 'dock'
|
|
}
|
|
|
|
export const useMenuStore = defineStore('menu', () => {
|
|
const display = reactive(defaultDisplay)
|
|
const mPos = {
|
|
x: 0,
|
|
y: 0
|
|
}
|
|
const handle = (e: MouseEvent) => {
|
|
mPos.x = e.pageX
|
|
mPos.y = e.pageY
|
|
}
|
|
window.addEventListener('mousemove', handle)
|
|
onUnmounted(() => {
|
|
window.removeEventListener('mousemove', handle)
|
|
})
|
|
const open = (type: (typeof defaultDisplay)['type']) => {
|
|
display.x = Math.min(window.innerWidth - 180, mPos.x)
|
|
display.y = Math.min(window.innerHeight - 220, mPos.y)
|
|
display.type = type
|
|
}
|
|
const show = computed(() => display.x > 0 && display.y > 0)
|
|
const dismiss = () => {
|
|
display.x = 0
|
|
display.y = 0
|
|
display.type = 'global'
|
|
}
|
|
return {
|
|
display,
|
|
open,
|
|
dismiss,
|
|
show
|
|
}
|
|
})
|
|
|
|
const Item = defineComponent({
|
|
props: {
|
|
alert: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
noStyle: {
|
|
type: Boolean,
|
|
default: false
|
|
}
|
|
},
|
|
emits: {
|
|
click: () => true
|
|
},
|
|
setup(props, ctx) {
|
|
return () => (
|
|
<div
|
|
class={clsx(
|
|
'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-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={() => {
|
|
ctx.emit('click')
|
|
}}
|
|
>
|
|
{ctx.slots.default?.()}
|
|
</div>
|
|
)
|
|
}
|
|
})
|
|
|
|
export default defineComponent(() => {
|
|
const menu = useMenuStore()
|
|
const settings = useSettingsStore()
|
|
const layout = useLayoutStore()
|
|
document.addEventListener('contextmenu', () => {
|
|
menu.open('global')
|
|
})
|
|
const router = useRouterStore()
|
|
const adderPage = useAdderPageStore()
|
|
return () =>
|
|
menu.show && (
|
|
<div
|
|
v-outside-click={() => {
|
|
menu.dismiss()
|
|
}}
|
|
class="fixed px-2 pt-4 pb-2 bg-white/60 backdrop-blur shadow-lg rounded-lg overflow-hidden"
|
|
style={{
|
|
zIndex: '999',
|
|
left: menu.display.x + 'px',
|
|
top: menu.display.y + 'px',
|
|
width: menu.display.type === 'global' ? '160px' : '120px'
|
|
}}
|
|
>
|
|
{(() => {
|
|
if (menu.display.type === 'global') {
|
|
// 全局菜单
|
|
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') {
|
|
// dock 栏
|
|
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
|
|
if (!block.link) {
|
|
// 小组件
|
|
const selected = widgetList.find((el) => el.name === block.name)
|
|
return (
|
|
<>
|
|
{selected?.list &&
|
|
selected.list.length > 1 &&
|
|
selected.list.map((el) => (
|
|
<Item
|
|
onClick={() => {
|
|
block.w = el.w
|
|
block.h = el.h
|
|
menu.dismiss()
|
|
}}
|
|
>
|
|
{el.label}
|
|
</Item>
|
|
))}
|
|
<Item
|
|
alert
|
|
onClick={() => {
|
|
// 删除链接
|
|
const idx = layout.currentPage.list.findIndex((el) => el.id === block.id)
|
|
if (idx < 0) return
|
|
layout.currentPage.list.splice(idx, 1)
|
|
menu.dismiss()
|
|
}}
|
|
>
|
|
删除
|
|
</Item>
|
|
</>
|
|
)
|
|
}
|
|
if (block.link.startsWith('id:')) {
|
|
// 文件夹
|
|
const id = block.link.slice(3)
|
|
return (
|
|
<>
|
|
<Item
|
|
onClick={() => {
|
|
block.w = 1
|
|
block.h = 1
|
|
menu.dismiss()
|
|
}}
|
|
>
|
|
小
|
|
</Item>
|
|
<Item
|
|
onClick={() => {
|
|
block.w = 2
|
|
block.h = 2
|
|
menu.dismiss()
|
|
}}
|
|
>
|
|
大
|
|
</Item>
|
|
<Item
|
|
onClick={() => {
|
|
menu.dismiss()
|
|
const idx = layout.currentPage.list.findIndex((el) => el.id === block.id)
|
|
if (idx < 0) return
|
|
layout.state.dir[id].list.forEach((val) => {
|
|
layout.addBlock(val, layout.state.currentPage)
|
|
})
|
|
layout.currentPage.list.splice(idx, 1)
|
|
delete layout.state.dir[id]
|
|
menu.dismiss()
|
|
}}
|
|
>
|
|
释放
|
|
</Item>
|
|
<Item
|
|
alert
|
|
onClick={() => {
|
|
// 删除文件夹
|
|
const idx = layout.currentPage.list.findIndex((el) => el.id === block.id)
|
|
if (idx < 0) return
|
|
layout.currentPage.list.splice(idx, 1)
|
|
delete layout.state.dir[id]
|
|
menu.dismiss()
|
|
}}
|
|
>
|
|
删除
|
|
</Item>
|
|
</>
|
|
)
|
|
}
|
|
// 链接
|
|
return (
|
|
<>
|
|
<Item>编辑</Item>
|
|
<Item
|
|
alert
|
|
onClick={() => {
|
|
// 删除链接
|
|
let idx = layout.currentPage.list.findIndex((el) => el.id === block.id)
|
|
if (idx < 0) {
|
|
// 查找文件夹
|
|
idx = layout.state.dir[layout.openDir]?.list?.findIndex(
|
|
(el) => el.id === block.id
|
|
)
|
|
if (idx === undefined || idx < 0) {
|
|
// 查找 dock
|
|
idx = layout.state.dock.findIndex((el) => el?.id === block.id)
|
|
if (idx >= 0) {
|
|
layout.state.dock[idx] = null
|
|
menu.dismiss()
|
|
}
|
|
} else {
|
|
const list = layout.state.dir[layout.openDir].list
|
|
list.splice(idx, 1)
|
|
layout.checkDir(layout.openDir)
|
|
menu.dismiss()
|
|
}
|
|
} else {
|
|
layout.currentPage.list.splice(idx, 1)
|
|
menu.dismiss()
|
|
}
|
|
}}
|
|
>
|
|
删除
|
|
</Item>
|
|
</>
|
|
)
|
|
})()}
|
|
</div>
|
|
)
|
|
})
|