完成小组件

This commit is contained in:
plightfield 2024-09-26 11:47:16 +08:00
parent b9dc48751f
commit acc091644c
11 changed files with 171 additions and 5 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@ -1,4 +1,12 @@
import { computed, defineComponent, ref, Transition } from 'vue'
import {
computed,
defineComponent,
provide,
ref,
Transition,
type InjectionKey,
type Ref
} from 'vue'
import AdderPageBack from './AdderPageBack'
import useLayoutStore from '../useLayoutStore'
import { OhVueIcon, addIcons } from 'oh-vue-icons'
@ -6,6 +14,8 @@ import { MdKeyboardcommandkey, FaCompass, FaPencilRuler } from 'oh-vue-icons/ico
import CustomAdder from './CustomAdder'
import clsx from 'clsx'
import ThemeProvider from '@/utils/ThemeProvider'
import WidgetAdder from './WidgetAdder'
import { Form, Input, Select } from 'ant-design-vue'
addIcons(MdKeyboardcommandkey, FaCompass, FaPencilRuler)
const ItemButton = defineComponent({
@ -50,10 +60,14 @@ const ItemButton = defineComponent({
}
})
export const AddToToken = Symbol('addTo') as InjectionKey<Ref<number>>
export default defineComponent(() => {
const layout = useLayoutStore()
const isGame = computed(() => layout.state.current === 0)
const type = ref(1)
const addTo = ref(layout.state.currentPage)
provide(AddToToken, addTo)
return () => (
<div class={clsx('w-full h-full relative flex', isGame.value && 'bg-[#2c2e3e]')}>
<ThemeProvider dark={isGame.value}>
@ -96,11 +110,25 @@ export default defineComponent(() => {
}
onContextmenu={(e) => e.stopPropagation()}
>
<div class="w-full h-[60px]"></div>
<Form class="w-full px-4 mt-4" layout="inline">
<Form.Item label="添加到">
<Select
style="width: 140px"
v-model:value={addTo.value}
options={layout.currentMode.pages.map((el, idx) => ({
label: el.label,
value: idx
}))}
/>
</Form.Item>
<Form.Item>
<Input.Search class="w-[200px]" placeholder="搜索组件或网站" />
</Form.Item>
</Form>
<div class="w-full h-0 flex-grow p-6">
<div class="w-full h-full relative">
<Transition>
{type.value === 0 ? '' : type.value === 1 ? '' : <CustomAdder />}
{type.value === 0 ? <WidgetAdder /> : type.value === 1 ? '' : <CustomAdder />}
</Transition>
</div>
</div>

View File

@ -1,4 +1,4 @@
import { computed, defineComponent, reactive, ref, watch } from 'vue'
import { computed, defineComponent, inject, reactive, ref, watch } from 'vue'
import useLayoutStore from '../useLayoutStore'
import { Button, Form, Input, InputGroup } from 'ant-design-vue'
import { OhVueIcon, addIcons } from 'oh-vue-icons'
@ -11,6 +11,7 @@ import type { Block } from '../layout.types'
import { ColorPicker } from 'vue3-colorpicker'
import 'vue3-colorpicker/style.css'
import { globalToast } from '@/main'
import { AddToToken } from './AdderPage'
addIcons(MdUpload, MdImage, MdCheck)
@ -150,6 +151,7 @@ export default defineComponent(() => {
if (val.name) form.name = val.name
if (val.icon) form.icon = val.icon
})
const addTo = inject(AddToToken)
return () => (
<div
class={
@ -242,7 +244,7 @@ export default defineComponent(() => {
form.type === 0 ? '' : form.text || form.name.substring(0, 2).toLocaleUpperCase(),
label: form.name
}
layout.addBlock(data)
layout.addBlock(data, addTo?.value)
}}
>

View File

@ -0,0 +1,69 @@
import { computed, defineComponent } from 'vue'
import useLayoutStore from '../useLayoutStore'
import widgetList, { type Widget } from '@/widgets'
import { Button } from 'ant-design-vue'
import clsx from 'clsx'
export const Item = defineComponent({
props: {
content: {
type: Object as () => Widget,
required: true
}
},
setup(props) {
const layout = useLayoutStore()
const isGame = computed(() => layout.state.current === 0)
return () => (
<div
class={clsx('bg-white w-full h-full rounded-lg shadow p-4', {
'bg-white/20': isGame.value,
'bg-white/80': !isGame.value
})}
key={props.content.name}
>
<div class="flex">
<img src={props.content.icon} class="w-[48px] h-[48px] bg-cover" />
<div class="px-2 w-0 flex-grow">
<div
class={clsx('text text-sm', {
'text-white': isGame.value,
'text-black/80': !isGame.value
})}
>
{props.content.label}
</div>
<div
class={clsx('text-[12px]', {
'text-white/80': isGame.value,
'text-black/60': !isGame.value
})}
>
{props.content.description}
</div>
</div>
</div>
<div class="flex justify-end">
<Button size="small" type="primary">
</Button>
</div>
</div>
)
}
})
export default defineComponent(() => {
return () => (
<div class="absolute left-0 top-0 w-full h-full overflow-y-auto gap-4">
<div
class="w-full grid grid-cols-3 grid-flow-row-dense pb-[200px]"
style="grid-auto-rows: 100px"
>
{widgetList.map((el) => (
<Item content={el} key={el.name} />
))}
</div>
</div>
)
})

View File

@ -64,6 +64,7 @@ export default defineStore('layout', () => {
// 添加图标
const addBlock = (block: Block, _page: number = -1) => {
const page = _page >= 0 ? _page : state.currentPage
console.log(page)
console.log(state.content[state.current].pages[page])
if (!state.content[state.current].pages[page]) {
globalToast.warning('请先添加页面')

View File

@ -0,0 +1,5 @@
import { defineComponent } from 'vue'
export default defineComponent(() => {
return () => <div class="w-full h-full bg-red-50"></div>
})

View File

@ -0,0 +1,5 @@
import { defineComponent } from 'vue'
export default defineComponent(() => {
return () => <div class="w-full h-full bg-red-50"></div>
})

View File

@ -0,0 +1,5 @@
import { defineComponent } from 'vue'
export default defineComponent(() => {
return () => <div class="w-full h-full bg-red-50"></div>
})

View File

@ -0,0 +1,5 @@
import { defineComponent } from 'vue'
export default defineComponent(() => {
return () => <div class="w-full h-full bg-red-50"></div>
})

View File

@ -0,0 +1,29 @@
import type { Widget } from '..'
export default {
name: 'calendar',
label: '日历',
description: '日历信息',
icon: '/icons/calendarIcon.png',
modal: () => import('./Modal'),
list: [
{
w: 2,
h: 1,
label: '小',
component: () => import('./Small')
},
{
w: 2,
h: 2,
label: '中',
component: () => import('./Middle')
},
{
w: 4,
h: 2,
label: '大',
component: () => import('./Large')
}
]
} as Widget

17
src/widgets/index.ts Normal file
View File

@ -0,0 +1,17 @@
import calendar from './calendar'
export interface Widget {
name: string // 小组件类型唯一标识
label: string // 小组件名称
description: string // 小组件描述
icon: string // 小组件图标
modal: () => any // 弹框组件
list: {
w: number
h: number
label: string
component: () => any
}[] // 不同尺寸小组件块
}
export default [calendar] as Widget[]