diff --git a/public/bg/addcomponentborder.png b/public/bg/addcomponentborder.png new file mode 100644 index 0000000..bf06cd1 Binary files /dev/null and b/public/bg/addcomponentborder.png differ diff --git a/public/bg/gamenews__back.png b/public/bg/gamenews__back.png new file mode 100644 index 0000000..95c4b60 Binary files /dev/null and b/public/bg/gamenews__back.png differ diff --git a/public/icons/gamenews__icon.png b/public/icons/gamenews__icon.png new file mode 100644 index 0000000..067b4c5 Binary files /dev/null and b/public/icons/gamenews__icon.png differ diff --git a/public/icons/gt.png b/public/icons/gt.png new file mode 100644 index 0000000..2fb3c69 Binary files /dev/null and b/public/icons/gt.png differ diff --git a/public/icons/hot_information_icon.png b/public/icons/hot_information_icon.png new file mode 100644 index 0000000..0cd2040 Binary files /dev/null and b/public/icons/hot_information_icon.png differ diff --git a/public/icons/mita.png b/public/icons/mita.png new file mode 100644 index 0000000..36a5520 Binary files /dev/null and b/public/icons/mita.png differ diff --git a/public/icons/note_pad_icon.png b/public/icons/note_pad_icon.png new file mode 100644 index 0000000..108278c Binary files /dev/null and b/public/icons/note_pad_icon.png differ diff --git a/public/icons/today_eat.png b/public/icons/today_eat.png new file mode 100644 index 0000000..a46e519 Binary files /dev/null and b/public/icons/today_eat.png differ diff --git a/public/icons/游戏资讯@2x.png b/public/icons/游戏资讯@2x.png new file mode 100644 index 0000000..e11a9b0 Binary files /dev/null and b/public/icons/游戏资讯@2x.png differ diff --git a/src/layout/adder/AdderPage.tsx b/src/layout/adder/AdderPage.tsx index 987111d..ee8094b 100644 --- a/src/layout/adder/AdderPage.tsx +++ b/src/layout/adder/AdderPage.tsx @@ -71,11 +71,10 @@ export default defineComponent(() => { return () => (
- {isGame.value && }
{ const sortBy = ref<'hotNum' | 'time'>('hotNum') onMounted(() => { - request('GET', '/api/backgroundTypes').then((res) => { + request('GET', '/api/app/backgroundTypes').then((res) => { console.log(res) typeList.value = res selectType.value = res[0].id @@ -69,7 +69,7 @@ export default defineComponent(() => { (e) => { if (!e[0]) return wallpaperList.value = [] - request('GET', `/api/backgrounds?typeId=${e[0]}&sort=${sortBy.value}`).then( + request('GET', `/api/app/backgrounds?typeId=${e[0]}&sort=${sortBy.value}`).then( (res) => { console.log(res) wallpaperList.value = res diff --git a/src/widgets/demo/Large.tsx b/src/widgets/demo/Large.tsx new file mode 100644 index 0000000..b83de91 --- /dev/null +++ b/src/widgets/demo/Large.tsx @@ -0,0 +1,9 @@ +import { defineComponent } from 'vue' + +export default defineComponent(() => { + return () => ( +
+ large +
+ ) +}) diff --git a/src/widgets/demo/Middle.tsx b/src/widgets/demo/Middle.tsx new file mode 100644 index 0000000..53edc23 --- /dev/null +++ b/src/widgets/demo/Middle.tsx @@ -0,0 +1,10 @@ +import { defineComponent } from 'vue' + +export default defineComponent(() => { + + return () => ( +
+ middle +
+ ) +}) diff --git a/src/widgets/demo/Modal.tsx b/src/widgets/demo/Modal.tsx new file mode 100644 index 0000000..9890740 --- /dev/null +++ b/src/widgets/demo/Modal.tsx @@ -0,0 +1,12 @@ +import { defineComponent } from 'vue' + +export default defineComponent(() => { + return () => ( +
+ ) +}) diff --git a/src/widgets/demo/Small.tsx b/src/widgets/demo/Small.tsx new file mode 100644 index 0000000..bf0a763 --- /dev/null +++ b/src/widgets/demo/Small.tsx @@ -0,0 +1,14 @@ +import { defineComponent } from 'vue' + +export default defineComponent(() => { + return () => ( +
+ +
+ ) +}) diff --git a/src/widgets/demo/index.ts b/src/widgets/demo/index.ts new file mode 100644 index 0000000..46a5db7 --- /dev/null +++ b/src/widgets/demo/index.ts @@ -0,0 +1,30 @@ +import asyncLoader from '@/utils/asyncLoader' +import type { Widget } from '..' + +export default { + name: 'gameNews', + label: '游戏资讯', + description: '游戏资讯', + icon: '/icons/game_news_icon.png', + modal: asyncLoader(() => import('./Modal')), + list: [ + { + w: 2, + h: 1, + label: '小', + component: asyncLoader(() => import('./Small')) + }, + { + w: 2, + h: 2, + label: '中', + component: asyncLoader(() => import('./Middle')) + }, + { + w: 4, + h: 2, + label: '大', + component: asyncLoader(() => import('./Large')) + } + ] +} as Widget diff --git a/src/widgets/gameNews/Large.tsx b/src/widgets/gameNews/Large.tsx new file mode 100644 index 0000000..e794326 --- /dev/null +++ b/src/widgets/gameNews/Large.tsx @@ -0,0 +1,28 @@ +import { defineComponent } from 'vue' +import useGameNews from './useGameNews' + +export default defineComponent(() => { + const store = useGameNews() + return () => ( +
+ {store.list + .filter((_, index) => index < 3) + .map((item) => ( +
+ +
+ + {item.title} + + {item.content} +
+
+ ))} +
+ ) +}) diff --git a/src/widgets/gameNews/Middle.tsx b/src/widgets/gameNews/Middle.tsx new file mode 100644 index 0000000..e794326 --- /dev/null +++ b/src/widgets/gameNews/Middle.tsx @@ -0,0 +1,28 @@ +import { defineComponent } from 'vue' +import useGameNews from './useGameNews' + +export default defineComponent(() => { + const store = useGameNews() + return () => ( +
+ {store.list + .filter((_, index) => index < 3) + .map((item) => ( +
+ +
+ + {item.title} + + {item.content} +
+
+ ))} +
+ ) +}) diff --git a/src/widgets/gameNews/Modal.tsx b/src/widgets/gameNews/Modal.tsx new file mode 100644 index 0000000..9450d42 --- /dev/null +++ b/src/widgets/gameNews/Modal.tsx @@ -0,0 +1,88 @@ +import { defineComponent, ref, watch, type VNodeRef } from 'vue' +import useGameNews from './useGameNews' +import { RiTimeLine } from 'oh-vue-icons/icons' +import { addIcons, OhVueIcon } from 'oh-vue-icons' +import dayjs from 'dayjs' +addIcons(RiTimeLine) +export default defineComponent(() => { + const store = useGameNews() + const containerRef = ref(null as VNodeRef | null) + + const handleScroll = () => { + const container = containerRef.value + console.log(container) + + if (container.scrollTop + container.clientHeight >= container.scrollHeight - 50) { + console.log('到底了') + + store.getNews() + } + } + return () => ( +
+
+ +
+
+
+
+ {store.list.map((item, index) => { + return ( +
{ + window.open(item.share_url) + }} + key={index} + > + + +
+ + {item.title} + + + {item.content} + +
+ + {dayjs(item.create_time * 1000).format('YYYY-MM-DD')} +
+
+
+ ) + })} +
+ {store.loading && ( +
加载中...
+ )} + {store.noMoreData && ( +
无更多数据
+ )} +
+
+
+ ) +}) diff --git a/src/widgets/gameNews/Small.tsx b/src/widgets/gameNews/Small.tsx new file mode 100644 index 0000000..35947e4 --- /dev/null +++ b/src/widgets/gameNews/Small.tsx @@ -0,0 +1,28 @@ +import { defineComponent } from 'vue' +import useGameNews from './useGameNews' + +export default defineComponent(() => { + const store = useGameNews() + return () => ( +
+ +
+
+ 游戏资讯 +
+ 立即查看 +
+ +
+
+
+
+
+ ) +}) diff --git a/src/widgets/gameNews/index.ts b/src/widgets/gameNews/index.ts new file mode 100644 index 0000000..46a5db7 --- /dev/null +++ b/src/widgets/gameNews/index.ts @@ -0,0 +1,30 @@ +import asyncLoader from '@/utils/asyncLoader' +import type { Widget } from '..' + +export default { + name: 'gameNews', + label: '游戏资讯', + description: '游戏资讯', + icon: '/icons/game_news_icon.png', + modal: asyncLoader(() => import('./Modal')), + list: [ + { + w: 2, + h: 1, + label: '小', + component: asyncLoader(() => import('./Small')) + }, + { + w: 2, + h: 2, + label: '中', + component: asyncLoader(() => import('./Middle')) + }, + { + w: 4, + h: 2, + label: '大', + component: asyncLoader(() => import('./Large')) + } + ] +} as Widget diff --git a/src/widgets/gameNews/useGameNews.ts b/src/widgets/gameNews/useGameNews.ts new file mode 100644 index 0000000..bed7c89 --- /dev/null +++ b/src/widgets/gameNews/useGameNews.ts @@ -0,0 +1,58 @@ +import request from "@/utils/request"; +import { defineStore } from "pinia"; +import { ref, type VNodeRef } from "vue"; + + +export interface GameNews { + id: number; + title: string; + content: string; + cover: string; + image: string; + create_time: number; + share_url: string; +} +export default defineStore("gameNews", () => { + const list = ref([]) + const page = ref(1) + const loading = ref(false) + const noMoreData = ref(false) + const containerRef = ref(null) + + const getList = async () => { + const res = await request<{ + data: GameNews[]; + }>('GET', `/api/gameDes?page=${page.value}&page_size=16`) + return res.data + } + const getNews = async () => { + + if (loading.value || noMoreData.value) return; + loading.value = true; + + try { + const data = await getList() + + if (data.length === 0) { + noMoreData.value = true; + } else { + list.value.push(...data); + page.value++; + } + } catch (e) { + console.log(e); + + } finally { + loading.value = false; + } + } + + getNews() + return { + list, + loading, + noMoreData, + getNews, + containerRef + } +}) \ No newline at end of file diff --git a/src/widgets/index.ts b/src/widgets/index.ts index 434b09c..5b8c45c 100644 --- a/src/widgets/index.ts +++ b/src/widgets/index.ts @@ -2,6 +2,7 @@ import type { Component } from 'vue' import calendar from './calendar' import weather from './weather' import weApply from './weApply' +import gameNews from './gameNews' export interface Widget { name: string // 小组件类型唯一标识 label: string // 小组件名称 @@ -16,4 +17,4 @@ export interface Widget { }[] // 不同尺寸小组件块 } -export default [calendar, weather, weApply] as Widget[] +export default [calendar, weather, weApply, gameNews] as Widget[] diff --git a/src/widgets/video/Large.tsx b/src/widgets/video/Large.tsx new file mode 100644 index 0000000..118526b --- /dev/null +++ b/src/widgets/video/Large.tsx @@ -0,0 +1,172 @@ +import { defineComponent, ref, watch, type VNodeRef } from 'vue' +import { useWeApplyStore } from './useWeApplyStore' +import { addIcons, OhVueIcon } from 'oh-vue-icons' +import { HiChevronDown } from 'oh-vue-icons/icons' +import clsx from 'clsx' +addIcons(HiChevronDown) +export default defineComponent(() => { + const store = useWeApplyStore() + const gameRef = ref(null) + const isGameBottom = ref(false) + const isWorkBottom = ref(false) + const workRef = ref(null) + const computIsBottom = (ref: any) => { + if (ref) { + const { scrollTop, clientHeight, scrollHeight } = ref + return scrollTop + clientHeight >= scrollHeight + } + } + const handleGameScroll = () => { + const isAtBottom = computIsBottom(gameRef.value) + console.log(isAtBottom ? '已滚动到底部!' : '未滚动到底部。') + if (isAtBottom) { + isGameBottom.value = true + } else { + isGameBottom.value = false + } + } + const handleWorkScroll = () => { + const isAtBottom = computIsBottom(workRef.value) + console.log(isAtBottom ? '已滚动到底部!' : '未滚动到底部。') + if (isAtBottom) { + isWorkBottom.value = true + } else { + isWorkBottom.value = false + } + } + watch(gameRef, (val, _, onCleanup) => { + console.log(val) + if (!val) return + val.addEventListener('scroll', handleGameScroll) + // if (val + gameRef.value.clientHeight >= gameRef.value.scrollHeight) { + // isGameBottom.value = true + // } else { + // isGameBottom.value = false + // } + onCleanup(() => { + val.removeEventListener('scroll', handleGameScroll) + }) + }) + watch(workRef, (val, _, onCleanup) => { + console.log(val) + if (!val) return + + val.addEventListener('scroll', handleWorkScroll) + // if (val + gameRef.value.clientHeight >= gameRef.value.scrollHeight) { + // isGameBottom.value = true + // } else { + // isGameBottom.value = false + // } + onCleanup(() => { + val.removeEventListener('scroll', handleWorkScroll) + }) + }) + return () => ( +
+
+ {!isGameBottom.value && ( +
{ + e.stopPropagation() + e.preventDefault() + if (gameRef.value) { + gameRef.value.scrollTop += 40 + } + }} + > + +
+ )} + +
{ + console.log('wheel') + }} + > + {store.state.list + .filter((val) => val.type === 'game') + .map((item) => ( +
+ game icon +
+ {item.name} + + {item.des} + +
+
+ ))} +
+
+
+ {!isWorkBottom.value && ( +
{ + e.stopPropagation() + e.preventDefault() + if (workRef.value) { + workRef.value.scrollTop += 20 + } + }} + > + +
+ )} + +
{ + console.log('wheel') + handleWorkScroll() + }} + > + {store.state.list + .filter((val) => val.type === 'work') + .map((item) => ( +
+ game icon +
+ {item.name} + + {item.des} + +
+
+ ))} +
+
+
+ ) +}) diff --git a/src/widgets/video/index.ts b/src/widgets/video/index.ts new file mode 100644 index 0000000..372edf2 --- /dev/null +++ b/src/widgets/video/index.ts @@ -0,0 +1,18 @@ +import asyncLoader from '@/utils/asyncLoader' +import type { Widget } from '..' + +export default { + name: 'video', + label: '视频', + description: '热门视频', + icon: '/icons/recommendedIcon.png', + modal: null, + list: [ + { + w: 4, + h: 2, + label: '大', + component: asyncLoader(() => import('./Large')) + } + ] +} as Widget diff --git a/src/widgets/video/useWeApplyStore.ts b/src/widgets/video/useWeApplyStore.ts new file mode 100644 index 0000000..805c66b --- /dev/null +++ b/src/widgets/video/useWeApplyStore.ts @@ -0,0 +1,29 @@ +import request from "@/utils/request" +import { defineStore } from "pinia" +import { reactive } from "vue" +type WeApplyType = { + id: string; + name: string; + url: string; + icon: string; + des: string; + type: string; +} +export const useWeApplyStore = defineStore('weApply', () => { + const state = reactive({ + list: [] as WeApplyType[] + }) + const getWeApplyList = async () => { + return request('GET', '/api/app/weApplys').then(res => { + return res + }) + } + const getList = async () => { + state.list = await getWeApplyList() + } + getList() + return { + state, + getList + } +}) \ No newline at end of file diff --git a/src/widgets/weApply/Large.tsx b/src/widgets/weApply/Large.tsx index 93687aa..9694486 100644 --- a/src/widgets/weApply/Large.tsx +++ b/src/widgets/weApply/Large.tsx @@ -13,12 +13,11 @@ export default defineComponent(() => { const computIsBottom = (ref: any) => { if (ref) { const { scrollTop, clientHeight, scrollHeight } = ref - return scrollTop + clientHeight >= scrollHeight + return scrollTop + clientHeight >= scrollHeight -8 } } const handleGameScroll = () => { const isAtBottom = computIsBottom(gameRef.value) - console.log(isAtBottom ? '已滚动到底部!' : '未滚动到底部。') if (isAtBottom) { isGameBottom.value = true } else { @@ -27,40 +26,13 @@ export default defineComponent(() => { } const handleWorkScroll = () => { const isAtBottom = computIsBottom(workRef.value) - console.log(isAtBottom ? '已滚动到底部!' : '未滚动到底部。') if (isAtBottom) { isWorkBottom.value = true } else { isWorkBottom.value = false } } - watch(gameRef, (val, _, onCleanup) => { - console.log(val) - if (!val) return - val.addEventListener('scroll', handleGameScroll) - // if (val + gameRef.value.clientHeight >= gameRef.value.scrollHeight) { - // isGameBottom.value = true - // } else { - // isGameBottom.value = false - // } - onCleanup(() => { - val.removeEventListener('scroll', handleGameScroll) - }) - }) - watch(workRef, (val, _, onCleanup) => { - console.log(val) - if (!val) return - val.addEventListener('scroll', handleWorkScroll) - // if (val + gameRef.value.clientHeight >= gameRef.value.scrollHeight) { - // isGameBottom.value = true - // } else { - // isGameBottom.value = false - // } - onCleanup(() => { - val.removeEventListener('scroll', handleWorkScroll) - }) - }) return () => (
{ e.preventDefault() if (gameRef.value) { gameRef.value.scrollTop += 40 + handleGameScroll() } }} > @@ -95,7 +68,7 @@ export default defineComponent(() => { ref={gameRef} class={clsx('w-full h-full flex flex-col overflow-y-scroll gap-y-2 scrollbar-hide ')} onWheel={() => { - console.log('wheel') + handleGameScroll() }} > {store.state.list @@ -133,6 +106,8 @@ export default defineComponent(() => { e.preventDefault() if (workRef.value) { workRef.value.scrollTop += 20 + handleWorkScroll() + } }} > @@ -144,7 +119,7 @@ export default defineComponent(() => { ref={workRef} class={clsx('w-full h-full flex flex-col overflow-y-scroll gap-y-2 scrollbar-hide ')} onWheel={() => { - console.log('wheel') + handleWorkScroll() }} > {store.state.list diff --git a/src/widgets/weApply/index.ts b/src/widgets/weApply/index.ts index fa76ef1..c349852 100644 --- a/src/widgets/weApply/index.ts +++ b/src/widgets/weApply/index.ts @@ -4,7 +4,7 @@ import type { Widget } from '..' export default { name: 'weApply', label: '大家都在用', - description: '大家都在用', + description: '盘点近期大热的应用软件和热门游戏', icon: '/icons/recommendedIcon.png', modal: null, list: [