添加网址导航-缺少搜索功能

This commit is contained in:
expdsn 2024-11-15 16:19:01 +08:00
parent e8d0a236dd
commit ade0c79a3c
5 changed files with 213 additions and 147 deletions

View File

@ -81,6 +81,7 @@ export default defineComponent(() => {
const isGame = computed(() => layout.state.current === 0) const isGame = computed(() => layout.state.current === 0)
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
@ -145,7 +146,27 @@ export default defineComponent(() => {
/> />
</Form.Item> </Form.Item>
<Form.Item> <Form.Item>
<Input.Search class="w-[200px]" placeholder="搜索组件或网站" /> <Input.Search
onSearch={(e) => {
if (store.type === 1) {
store.search(e)
} else if (store.type === 0) {
store.widgetSearchWords = e
} else if (store.type === 3) {
store.gameSearch = e
}
}}
class="w-[220px]"
placeholder={
store.type === 0
? '搜索想要添加的组件'
: store.type === 1
? '搜索想要添加的网址导航'
: store.type === 2
? ''
: '搜索想要添加的游戏'
}
/>
</Form.Item> </Form.Item>
</Form> </Form>
<div class="w-full h-0 flex-grow p-6"> <div class="w-full h-0 flex-grow p-6">

View File

@ -9,6 +9,7 @@ import { frontAddress, ossBase } from '@/config'
import dayjs from 'dayjs' import dayjs from 'dayjs'
import { generateRandomString } from '@/utils/tool' import { generateRandomString } from '@/utils/tool'
import MD5 from 'crypto-js/md5' import MD5 from 'crypto-js/md5'
import useAdderPageStore from './useAdderPageStore'
export const SECRET = 'A1Cv12olxT12dOE3xA1vPA==' export const SECRET = 'A1Cv12olxT12dOE3xA1vPA=='
export const URL_ADDRESS = 'http://newfatfox.oss-cn-beijing.aliyuncs.com' export const URL_ADDRESS = 'http://newfatfox.oss-cn-beijing.aliyuncs.com'
export interface GameType { export interface GameType {
@ -126,9 +127,9 @@ export const GameItem = defineComponent({
id: uuid(), id: uuid(),
link: !props.content.rom.startsWith('http') link: !props.content.rom.startsWith('http')
? `${frontAddress}/emu/#/home?params=${JSON.stringify({ ? `${frontAddress}/emu/#/home?params=${JSON.stringify({
...props.content, ...props.content,
rom: ossBase + '/' + props.content.rom rom: ossBase + '/' + props.content.rom
})}` })}`
: props.content.rom, : props.content.rom,
name: '', name: '',
label: props.content.name, label: props.content.name,
@ -159,6 +160,7 @@ export default defineComponent(() => {
const isGame = computed(() => layout.state.current === 0) const isGame = computed(() => layout.state.current === 0)
const appList = ref<GameType[]>([]) const appList = ref<GameType[]>([])
const selectType = ref('fc') const selectType = ref('fc')
const store = useAdderPageStore()
const fetchGame = async (page: number) => { const fetchGame = async (page: number) => {
const parems = `nonce=${generateRandomString(8)}&pid=PIDc8uT24mpo&timestamp=${dayjs().unix()}` const parems = `nonce=${generateRandomString(8)}&pid=PIDc8uT24mpo&timestamp=${dayjs().unix()}`
const sign = MD5(parems + SECRET).toString() const sign = MD5(parems + SECRET).toString()
@ -169,11 +171,11 @@ export default defineComponent(() => {
return res.data.items return res.data.items
} }
watch( watch(
selectType, [selectType, () => store.gameSearch],
(val) => { (val) => {
loading.value = true loading.value = true
if (val !== 'yiqiyoo') { if (val[0] !== 'yiqiyoo') {
request<GameType[]>('GET', `/api/games?type=${val}`) request<GameType[]>('GET', `/api/games?type=${val[0]}&keyword=${val[1]}`)
.then((res) => { .then((res) => {
appList.value = res appList.value = res
}) })
@ -212,41 +214,44 @@ export default defineComponent(() => {
) )
return () => ( return () => (
<div class={'w-full h-full flex flex-col gap-y-4'}> <div class={'w-full h-full flex flex-col gap-y-4'}>
<div class={'w-full '}> {!store.gameSearch && (
<CategoryTab <div class={'w-full '}>
list={DefautGameTypeList} <CategoryTab
selectType={selectType.value} list={DefautGameTypeList}
onUpdate:type={(e) => { selectType={selectType.value}
selectType.value = e onUpdate:type={(e) => {
}} selectType.value = e
v-slots={{ }}
select: (text: string) => ( v-slots={{
<button select: (text: string) => (
class={clsx( <button
'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap ', class={clsx(
isGame.value 'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap ',
? 'bg-white/30 text-white bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]' isGame.value
: 'text-white bg-[#D6D6D6] bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]' ? 'bg-white/30 text-white bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]'
)} : 'text-white bg-[#D6D6D6] bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]'
> )}
{text} >
</button> {text}
), </button>
unSelect: (text: string) => ( ),
<button unSelect: (text: string) => (
class={clsx( <button
'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap', class={clsx(
isGame.value 'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap',
? ' text-[#999] bg-white/10 hover:bg-white/20' isGame.value
: 'text-[#666] hover:bg-black/10 bg-black/[0.05] hover:bg-[#f0ecec]' ? ' text-[#999] bg-white/10 hover:bg-white/20'
)} : 'text-[#666] hover:bg-black/10 bg-black/[0.05] hover:bg-[#f0ecec]'
> )}
{text} >
</button> {text}
) </button>
}} )
></CategoryTab> }}
</div> ></CategoryTab>
</div>
)}
<div class={'h-0 flex-1 w-full'}> <div class={'h-0 flex-1 w-full'}>
<div class={'w-full h-full overflow-y-scroll scrollbar-hide'}> <div class={'w-full h-full overflow-y-scroll scrollbar-hide'}>
{!loading.value ? ( {!loading.value ? (

View File

@ -1,26 +1,11 @@
import CategoryTab from '@/utils/CategoryTab' import CategoryTab from '@/utils/CategoryTab'
import request from '@/utils/request' import { computed, defineComponent, inject } from 'vue'
import { computed, defineComponent, inject, onMounted, ref, watch } from 'vue'
import type { BackgroundType } from '../background/BackgroundSwtich'
import clsx from 'clsx' import clsx from 'clsx'
import useLayoutStore from '../useLayoutStore' import useLayoutStore from '../useLayoutStore'
import { AddToToken } from './AdderPage' import { AddToToken } from './AdderPage'
import { v4 as uuid } from 'uuid' import { v4 as uuid } from 'uuid'
import useAdderPageStore, { type HotAppType } from './useAdderPageStore'
interface HotAppCategoryType {
id: string
name: string
ordinal: number
}
interface HotAppType {
id: string
name: string
url: string
ordinal: number
desc: string
icon: string
background: string
}
export const LinkItem = defineComponent({ export const LinkItem = defineComponent({
props: { props: {
content: { content: {
@ -34,10 +19,13 @@ export const LinkItem = defineComponent({
const addTo = inject(AddToToken) const addTo = inject(AddToToken)
return () => ( return () => (
<div <div
class={clsx(' w-full h-full rounded-lg relative flex flex-col justify-between overflow-hidden shadow p-4', { class={clsx(
'bg-white/20': isGame.value, ' w-full h-full rounded-lg relative flex flex-col justify-between overflow-hidden shadow p-4',
'bg-white/80': !isGame.value {
})} 'bg-white/20': isGame.value,
'bg-white/80': !isGame.value
}
)}
key={props.content.name} key={props.content.name}
> >
<div <div
@ -110,6 +98,9 @@ export const LinkItem = defineComponent({
}, },
addTo?.value addTo?.value
) )
if (addTo?.value) {
layout.state.currentPage = addTo?.value
}
}} }}
> >
@ -122,78 +113,55 @@ export const LinkItem = defineComponent({
export default defineComponent(() => { export default defineComponent(() => {
const layout = useLayoutStore() const layout = useLayoutStore()
const loading = ref(false)
const isGame = computed(() => layout.state.current === 0) const isGame = computed(() => layout.state.current === 0)
const appList = ref<HotAppType[]>([])
const categoryList = ref<BackgroundType[]>([])
const selectType = ref('')
onMounted(() => {
request<HotAppCategoryType[]>('GET', '/api/app/hotAppTypes').then((res) => {
categoryList.value = res.map((el) => ({
id: el.id,
oridinal: el.ordinal,
type: el.name,
attr: 0
}))
selectType.value = res[0].id const store = useAdderPageStore()
})
})
watch(selectType, (val) => {
loading.value = true
request<HotAppType[]>('GET', `/api/app/hotApps?hotAppsId=${val}`)
.then((res) => {
appList.value = res
})
.finally(() => {
setTimeout(() => {
loading.value = false
}, 200)
})
})
return () => ( return () => (
<div class={'w-full h-full flex flex-col gap-y-4'}> <div class={'w-full h-full flex flex-col gap-y-4'}>
<div class={'w-full '}> {!store.isSearch && (
<CategoryTab <div class={'w-full '}>
list={categoryList.value} <CategoryTab
selectType={selectType.value} list={store.categoryList}
onUpdate:type={(e) => { selectType={store.selectType}
selectType.value = e onUpdate:type={(e) => {
}} store.selectType = e
v-slots={{ }}
select: (text: string) => ( v-slots={{
<button select: (text: string) => (
class={clsx( <button
'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap ', class={clsx(
isGame.value 'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap ',
? 'bg-white/30 text-white bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]' isGame.value
: 'text-white bg-[#D6D6D6] bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]' ? 'bg-white/30 text-white bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]'
)} : 'text-white bg-[#D6D6D6] bg-gradient-to-b from-[#ffaa4e] to-[#ff6227]'
> )}
{text} >
</button> {text}
), </button>
unSelect: (text: string) => ( ),
<button unSelect: (text: string) => (
class={clsx( <button
'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap', class={clsx(
isGame.value 'px-[20px] text-[14px] py-1 items-center justify-center duration-75 shrink-0 flex rounded-2xl whitespace-nowrap',
? ' text-[#999] bg-white/10 hover:bg-white/20' isGame.value
: 'text-[#666] hover:bg-black/10 bg-black/[0.05] hover:bg-[#f0ecec]' ? ' text-[#999] bg-white/10 hover:bg-white/20'
)} : 'text-[#666] hover:bg-black/10 bg-black/[0.05] hover:bg-[#f0ecec]'
> )}
{text} >
</button> {text}
) </button>
}} )
></CategoryTab> }}
</div> ></CategoryTab>
</div>
)}
<div class={'h-0 flex-1 w-full'}> <div class={'h-0 flex-1 w-full'}>
<div class={'w-full h-full overflow-y-scroll scrollbar-hide'}> <div class={'w-full h-full overflow-y-scroll scrollbar-hide'}>
{!loading.value ? ( {!store.loading ? (
<div class={'w-full grid grid-cols-3 gap-4 '} style="grid-auto-rows: 120px"> <div class={'w-full grid grid-cols-3 gap-4 '} style="grid-auto-rows: 120px">
{appList.value.map((el) => ( {store.appList.map((el) => (
<LinkItem content={el}></LinkItem> <LinkItem content={el}></LinkItem>
))} ))}
</div> </div>

View File

@ -4,6 +4,7 @@ import widgetList, { type Widget } from '@/widgets'
import clsx from 'clsx' import clsx from 'clsx'
import { AddToToken } from './AdderPage' import { AddToToken } from './AdderPage'
import { v4 as uuid } from 'uuid' import { v4 as uuid } from 'uuid'
import useAdderPageStore from './useAdderPageStore'
export const WidgetItem = defineComponent({ export const WidgetItem = defineComponent({
props: { props: {
@ -32,10 +33,7 @@ export const WidgetItem = defineComponent({
key={props.content.name} key={props.content.name}
> >
<div class="flex"> <div class="flex">
<img <img src={props.content.icon} class="w-[58px] h-[58px] bg-cover rounded-lg shadow-lg" />
src={props.content.icon}
class="w-[58px] h-[58px] bg-cover rounded-lg shadow-lg"
/>
<div class="px-2 w-0 flex-grow "> <div class="px-2 w-0 flex-grow ">
<div <div
class={clsx('text text-sm mb-[2px]', { class={clsx('text text-sm mb-[2px]', {
@ -120,18 +118,18 @@ export const WidgetItem = defineComponent({
export default defineComponent(() => { export default defineComponent(() => {
const layout = useLayoutStore() const layout = useLayoutStore()
const store = useAdderPageStore()
return () => ( return () => (
<div class="absolute left-0 top-0 w-full h-full overflow-y-auto scrollbar-hide gap-4"> <div class="absolute left-0 top-0 w-full h-full overflow-y-auto scrollbar-hide gap-4">
<div class="w-full grid grid-cols-3 grid-flow-row-dense gap-4" style="grid-auto-rows: 120px"> <div class="w-full grid grid-cols-3 grid-flow-row-dense gap-4" style="grid-auto-rows: 120px">
{ {layout.state.current !== 1
layout.state.current !== 1 ? ? widgetList
widgetList.filter(val => val.name !== 'tomato_work').map((el) => ( .filter((val) => val.name !== 'tomato_work')
<WidgetItem content={el} key={el.name} /> .filter((val) => val.label.includes(store.widgetSearchWords))
)) : .map((el) => <WidgetItem content={el} key={el.name} />)
widgetList.map((el) => ( : widgetList
<WidgetItem content={el} key={el.name} /> .filter((val) => val.label.includes(store.widgetSearchWords))
)) .map((el) => <WidgetItem content={el} key={el.name} />)}
}
</div> </div>
</div> </div>
) )

View File

@ -1,9 +1,83 @@
import { defineStore } from "pinia"; import request from '@/utils/request'
import { ref } from "vue"; import { defineStore } from 'pinia'
import { watch } from 'vue'
import { ref } from 'vue'
import type { BackgroundType } from '../background/BackgroundSwtich'
export interface HotAppType {
id: string
name: string
url: string
ordinal: number
desc: string
icon: string
background: string
}
export interface HotAppCategoryType {
id: string
name: string
ordinal: number
}
export default defineStore('adderPage', () => {
const type = ref(1)
const selectType = ref('')
const loading = ref(false)
const appList = ref<HotAppType[]>([])
const categoryList = ref<BackgroundType[]>([])
const isSearch = ref(false)
const widgetSearchWords = ref('')
const gameSearch = ref('')
request<HotAppCategoryType[]>('GET', '/api/app/hotAppTypes').then((res) => {
categoryList.value = res.map((el) => ({
id: el.id,
oridinal: el.ordinal,
type: el.name,
attr: 0
}))
export default defineStore("adderPage", () => { selectType.value = res[0].id
const type = ref(1) })
return { watch(selectType, (val) => {
type getApps(val)
})
const getApps = (_selectType: string) => {
loading.value = true
request<HotAppType[]>('GET', `/api/app/hotApps?hotAppsId=${_selectType}`)
.then((res) => {
appList.value = res
})
.finally(() => {
setTimeout(() => {
loading.value = false
}, 200)
})
}
const search = (keywords: string) => {
if (keywords === '') {
isSearch.value = false
getApps(selectType.value)
return
} }
}) isSearch.value = true
request<HotAppType[]>('GET', `/api/app/hotApp/search?keyword=${keywords}`)
.then((res) => {
appList.value = res
})
.finally(() => {
setTimeout(() => {
loading.value = false
}, 200)
})
}
return {
type,
widgetSearchWords,
categoryList,
appList,
loading,
selectType,
search,
isSearch,
gameSearch
}
})