完成了热点资讯

This commit is contained in:
expdsn 2024-10-22 16:27:19 +08:00
parent be58156b6d
commit c1ac61c3fd
16 changed files with 410 additions and 83 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 896 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -26,7 +26,7 @@ export default defineComponent({
const hover = ref(false)
return () => (
<div
class="w-full h-full p-[var(--block-padding)] relative rounded-lg hover-move"
class="w-full h-full p-[var(--block-padding)] relative rounded-lg "
key={props.block.id}
id={props.block.id}
style={{
@ -111,33 +111,35 @@ export default defineComponent({
}
}}
>
<div
class="w-full h-full overflow-hidden relative cursor-pointer shadow-lg"
style={{
borderRadius: `calc(var(--block-radius) * var(--block-size))`
}}
>
{props.block.link ? (
props.block.link.startsWith('id:') ? (
// 文件夹
<DirBlock block={props.block} big={props.block.w !== 1 || props.block.h !== 1} />
<div class={'w-full h-full relative'}>
<div
class="w-full h-full overflow-hidden relative cursor-pointer shadow-lg"
style={{
borderRadius: `calc(var(--block-radius) * var(--block-size))`
}}
>
{props.block.link ? (
props.block.link.startsWith('id:') ? (
// 文件夹
<DirBlock block={props.block} big={props.block.w !== 1 || props.block.h !== 1} />
) : (
// 链接
<LinkBlock block={props.block} />
)
) : (
// 链接
<LinkBlock block={props.block} />
)
) : (
// 小组件
<WidgetBlock block={props.block} />
// 小组件
<WidgetBlock block={props.block} />
)}
</div>
{settings.state.showBlockLabel && (
<div
class="absolute left-0 -bottom-7 text-sm text-white text-center w-full overflow-hidden text-ellipsis whitespace-nowrap break-all font-bold"
style="text-shadow: 0 0 4px rgba(0,0,0,.6)"
>
{layout.getLabel(props.block)}
</div>
)}
</div>
{settings.state.showBlockLabel && (
<div
class="absolute left-0 -bottom-2 text-sm text-white text-center w-full overflow-hidden text-ellipsis whitespace-nowrap break-all font-bold"
style="text-shadow: 0 0 4px rgba(0,0,0,.6)"
>
{layout.getLabel(props.block)}
</div>
)}
</div>
)
}

View File

@ -165,7 +165,13 @@ body {
scrollbar-width: none;
-ms-overflow-style: none;
}
.hover-move {
transform: translateY(0);
animation: none;
transition-duration: 0.3s;
transition-property: transform;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
.hover-move:hover {
transform: translateY(-4px);
}

View File

@ -56,7 +56,8 @@ export default defineComponent(() => {
}
>
<img
onClick={() => {
onClick={(e) => {
e.stopPropagation()
page.value = (page.value % 2) + 1
}}
class={clsx(

View File

@ -2,17 +2,17 @@ import { defineComponent, ref, watch, type VNodeRef } from 'vue'
import useGameNews from './useDiscountStore'
import { RiTimeLine } from 'oh-vue-icons/icons'
import { addIcons, OhVueIcon } from 'oh-vue-icons'
import { IoCloseCircleOutline, RiCloseCircleLine } from 'oh-vue-icons/icons'
import dayjs from 'dayjs'
addIcons(RiTimeLine)
addIcons(RiTimeLine, IoCloseCircleOutline, RiCloseCircleLine)
export default defineComponent(() => {
const store = useGameNews()
const containerRef = ref<VNodeRef | null>(null as VNodeRef | null)
const searchText = ref('')
const handleScroll = () => {
const container = containerRef.value
if (container.scrollTop + container.clientHeight >= container.scrollHeight - 50) {
store.getNews()
}
}
@ -24,46 +24,74 @@ export default defineComponent(() => {
}}
>
<div class={'flex w-full justify-center pb-5'}>
<img class={'h-[20px]'} src="/icons/游戏资讯@2x.png"></img>
<div class={'relative group'}>
<input
class={
'py-1 px-5 bg-white/20 rounded-2xl w-[440px] text-white border-none outline-none'
}
value={searchText.value}
placeholder="请输入搜索内容"
onInput={(e: any) => {
searchText.value = e.target.value
}}
onKeydown={(e: any) => {
if (e.key === 'Enter') {
store.getNews()
}
}}
></input>
<div class={'absolute cursor-pointer hidden group-hover:block right-3 top-1/2 -translate-y-1/2'}>
<OhVueIcon name={RiCloseCircleLine.name} fill="#ddd"></OhVueIcon>
</div>
</div>
</div>
<div class={'h-0 w-full flex-1'}>
<div class={'w-full h-full overflow-y-scroll'} onWheel={handleScroll} ref={containerRef}>
<div class={'grid grid-cols-2 gap-4 '}>
<div
class={'w-full h-full overflow-y-scroll scrollbar-hide'}
onWheel={handleScroll}
ref={containerRef}
>
<div class={'grid grid-cols-3 gap-4 '}>
{store.list.map((item, index) => {
return (
<div
class={
'flex cursor-pointer items-center h-[110px] rounded-lg relative overflow-hidden'
'flex cursor-pointer h-[215px] overflow-hidden bg-[#17212d] items-center flex-col rounded-lg relative '
}
onClick={()=> {
}}
onClick={() => {}}
key={index}
>
<img class={'h-[142px] w-full object-cover'} src={item.commdity[0]?.img}></img>
<div
class={
' absolute right-0 top-0 w-[70%] h-full rounded-xl flex flex-col justify-between py-4 text-white pl-2 overflow-hidden'
'absolute bottom-0 w-full h-[100px] rounded-lg bg-[#0003] backdrop-blur-md'
}
style={{
backdropFilter: 'blur(16px)',
backgroundColor: '#17212d',
background: 'rgba(0, 0, 0, .2)'
}}
>
<span class={'text-nowrap text-ellipsis overflow-hidden text-[14px]'}>
{item.gameid}
</span>
<span
class={' text-ellipsis overflow-hidden text-[12px] opacity-60 line-clamp-2'}
>
{item.name}
</span>
<div class={'text-[12px] items-center flex opacity-40 gap-x-1'}>
<OhVueIcon
name={RiTimeLine.name}
class={'text-white'}
scale={0.7}
></OhVueIcon>
<div class="flex flex-col w-full h-full justify-between py-2 px-3">
<span class="text-white text-[14px]">{item.name}</span>
<div>
<span
class={
'border-[1px] border-[#f6d1b8] border-solid text-[#f6d1b8] p-1 text-[12px] rounded'
}
>
{item.typename}
</span>
</div>
<div class="bg-white/20 flex rounded items-center">
<div class="bg-[#ef5a41] h-full text-white rounded px-2 text-[18px] font-bold ">
-13%
</div>
<span class="text-[#fffbc2] text-[16px] ml-2">
{item.commdity[0].price}
</span>
<span class="text-[12px] text-[#bdbdbd] line-through decoration-current">
{item.commdity[0].oldprice}
</span>
<span class="text-[12px] text-[#ebebeb] line-through decoration-current">
{item.commdity[0].oldprice}
</span>
</div>
</div>
</div>
</div>

View File

@ -1,9 +1,17 @@
import request from "@/utils/request";
import { defineStore } from "pinia";
import { ref, type VNodeRef } from "vue";
import { reactive, ref, type VNodeRef } from "vue";
type CommdityType = {
commodityClass: string;
img: string;
price: string;
oldprice: string;
royaltyrate: string
url: string;
}
export interface GameDiscount {
commdity: CommdityType[];
gameid: string;
status: number;
typeid: string;
@ -12,30 +20,34 @@ export interface GameDiscount {
}
export default defineStore("gameDiscount", () => {
const list = ref<GameDiscount[]>([])
const page = ref(1)
const loading = ref(false)
const noMoreData = ref(false)
const containerRef = ref<VNodeRef | null>(null)
const state = reactive({
pageId: 1,
name: '',
})
const getList = async () => {
const res = await request<{
data: GameDiscount[];
}>('GET', `/api/gameDiscount?page=${page.value}&page_size=16`)
}>('POST', '/api/gameDiscount', {
data: {
pageId: state.pageId,
name: state.name
}
})
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++;
state.pageId += 1;
}
} catch (e) {
console.log(e);
@ -51,6 +63,6 @@ export default defineStore("gameDiscount", () => {
loading,
noMoreData,
getNews,
containerRef
state,
}
})

View File

@ -1,9 +1,72 @@
import { defineComponent } from 'vue'
import useHotspotStore, { PlatformList } from './useHotspotStore'
import clsx from 'clsx'
import jump from '@/utils/jump'
export default defineComponent(() => {
const store = useHotspotStore()
return () => (
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
large
<div class="w-full h-full bg-[#e4eaff] flex flex-col">
<div class={'w-full rounded-xl flex px-2 justify-around '}>
{[...PlatformList.entries()].map(([key, value]) => (
<div
key={key}
onClick={(e) => {
store.type = key
e.stopPropagation()
}}
class={clsx(
' py-2 cursor-pointer bg rounded-xl flex gap-x-1 relative',
store.type === key ? 'text-[#4162ce] font-bold' : ''
)}
>
<span class={'z-10'}>{value}</span>
{store.type === key && (
<img
src="/icons/hotspot/hot_tab_bg.png"
class={'w-[26px] h-[11px] object-cover absolute -right-3 bottom-2'}
alt="bg"
/>
)}
</div>
))}
</div>
<div class={'w-full h-0 flex-1 '}>
<div class="px-3 py-2 w-full bg-white rounded-xl h-full flex flex-col justify-between">
{store.hotMap
.get(store.type)
?.filter((_, idx) => idx < 5)
.map((item, index) => (
<div
key={index}
class={'flex items-center gap-x-4 justify-between cursor-pointer group'}
onClick={() => {
jump(item.url)
}}
>
<div class={'flex items-center w-[260px] gap-x-2 text-ellipsis overflow-hidden '}>
<span
class={clsx('text-[#666] flex justify-center items-center rounded', {
'text-[#ff3300] ': index === 0,
'text-[#ff7e00] ': index === 1,
'text-[#ffc600] ': index === 2
})}
>
{index + 1}.
</span>
<span
class={
'text-[#666] items-center whitespace-nowrap overflow-hidden text-ellipsis group-hover:text-[#477aff] text-[14px] leading-[14px]'
}
>
{item.title}
</span>
</div>
<span class="text-[#999] text-[12px]">{item.hotScore}</span>
</div>
))}
</div>
</div>
</div>
)
})

View File

@ -1,10 +1,82 @@
import { defineComponent } from 'vue'
import useHotspotStore, { PlatformList } from './useHotspotStore'
import clsx from 'clsx'
import { BiCaretRightFill } from 'oh-vue-icons/icons'
import jump from '@/utils/jump'
import { addIcons, OhVueIcon } from 'oh-vue-icons'
addIcons(BiCaretRightFill)
export default defineComponent(() => {
const store = useHotspotStore()
return () => (
<div class="w-full h-full bg-[#ecfbff] flex flex-col">
middle
<div class="w-full h-full bg-[#e4eaff] flex flex-col">
<div class={'w-full rounded-xl flex px-2 justify-between items-center '}>
<div>
{[...PlatformList.entries()]
.filter((_, idx) => idx === 0)
.map(([key, value]) => (
<div
key={key}
onClick={(e) => {
store.type = key
e.stopPropagation()
}}
class={clsx(
' py-2 cursor-pointer bg rounded-xl flex gap-x-1 relative',
store.type === key ? 'text-[#4162ce] font-bold' : ''
)}
>
<span class={'z-10'}>{value}</span>
{store.type === key && (
<img
src="/icons/hotspot/hot_tab_bg.png"
class={'w-[26px] h-[11px] object-cover absolute -right-3 bottom-2'}
alt="bg"
/>
)}
</div>
))}
</div>
<div>
<OhVueIcon name={BiCaretRightFill.name} fill="#9B9B9B"></OhVueIcon>
</div>
</div>
<div class={'w-full h-0 flex-1 '}>
<div class="px-3 w-full bg-white rounded-xl h-full flex flex-col justify-between">
{store.hotMap
.get(store.type)
?.filter((_, idx) => idx < 5)
.map((item, index) => (
<div
key={index}
class={'flex items-center gap-x-4 justify-between cursor-pointer group'}
onClick={() => {
jump(item.url)
}}
>
<div class={'flex items-center w-[85px] gap-x-2 '}>
<span
class={clsx('text-[#666] flex justify-center items-center rounded', {
'text-[#ff3300] ': index === 0,
'text-[#ff7e00] ': index === 1,
'text-[#ffc600] ': index === 2
})}
>
{index + 1}.
</span>
<span
class={
'text-[#666] items-center whitespace-nowrap overflow-hidden text-ellipsis group-hover:text-[#477aff] text-[14px] leading-[14px]'
}
>
{item.title}
</span>
</div>
<span class="text-[#999] text-[12px]">{item.hotScore}</span>
</div>
))}
</div>
</div>
</div>
)
})

View File

@ -1,12 +1,76 @@
import { defineComponent } from 'vue'
import useHotspotStore, { PlatformList } from './useHotspotStore'
import clsx from 'clsx'
import jump from '@/utils/jump'
export default defineComponent(() => {
const store = useHotspotStore()
return () => (
<div
class="w-full h-full bg-red-50 flex "
style={{
background: 'linear-gradient(180deg,#dcefff 0%,#e7ecff 100%)'
}}
></div>
<div class="w-full h-full bg-[#e4eaff] flex flex-col">
<div class={'w-full h-[47px] flex items-center justify-center'}>
<img src="/icons/热搜榜@2x.png" class={'w-[65px] object-cover'}></img>
</div>
<div class={'flex-1 h-0'}>
<div class={'flex w-full h-full bg-white'}>
<div class={'w-[200px] bg-[#f4f4f4] rounded-xl flex flex-col px-2 pt-5 gap-y-2'}>
{[...PlatformList.entries()].map(([key, value]) => (
<div
key={key}
onClick={() => {
store.type = key
}}
class={clsx(
'w-full py-3 cursor-pointer pl-3 bg rounded-xl flex gap-x-1',
store.type === key
? 'bg-[#ffffff] text-[#4162ce] font-bold'
: 'hover:bg-[#ffffff] text-[#666]'
)}
>
<img
src={`/icons/hotspot/${key}_info.png`}
class={'w-[24px] h-[24px] object-cover'}
></img>
<span>{value}</span>
</div>
))}
</div>
<div class={'w-0 flex-1 '}>
<div class="p-7 w-full h-full flex flex-col gap-y-3 overflow-y-scroll">
{store.hotMap.get(store.type)?.map((item, index) => (
<div
key={index}
class={'flex items-center justify-between cursor-pointer group'}
onClick={() => {
jump(item.url)
}}
>
<div class={"flex items-center gap-x-2"}>
<span
class={clsx(
'text-[#666] w-[22px] h-[22px] flex justify-center items-center rounded',
{
'bg-[#ff3300] text-white ': index === 0,
'bg-[#ff7e00] text-white': index === 1,
'bg-[#ffc600] text-white': index === 2
}
)}
>
{index + 1}
</span>
<span
class={'text-[#666] group-hover:text-[#477aff] text-[14px] leading-[14px]'}
>
{item.title}
</span>
</div>
<span class="text-[#999] text-[12px]">{item.hotScore}</span>
</div>
))}
</div>
</div>
</div>
</div>
</div>
)
})

View File

@ -1,14 +1,25 @@
import { defineComponent } from 'vue'
export default defineComponent(() => {
return () => (
<div
class="w-full h-full items-center pl-3 gap-x-2 flex py-3 text-white"
style={{
background: 'linear-gradient(135deg,#5996ff 0%,#4862ff 100%)'
}}
class="w-full h-full flex items-center px-3 bg-[#405fd2]"
>
<img class={'w-[48px] h-[48px]'} src={'/icons/hot_information_icon.png'}></img>
<div class={'flex-1 flex justify-center'}>
<div class="flex-col flex">
<span class={'text-[16px] text-white'}></span>
<div class={'flex items-center text-[#fffc] text-[12px] '}>
<div>
<img src="/icons/gt.png"></img>
</div>
</div>
</div>
</div>
</div>
)
})

View File

@ -0,0 +1,49 @@
import useLayoutStore from '@/layout/useLayoutStore'
import request from '@/utils/request'
import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'
type HotType = {
desc: string
hotScore: string
index: number
picurl: string
title: string
url: string
}
export const PlatformList = new Map<string, string>([
['baidu', '百度'],
['weibo', '微博'],
['bilibili', 'B站']
] as const)
export default defineStore('hotspot', () => {
const hotMap = ref<Map<string, HotType[]>>(new Map())
const type = ref('baidu')
const addHotType = (key: string, hotType: HotType[]) => {
if (hotMap.value.has(key)) {
// 如果 key 已存在,向对应的数组中添加新元素
return
} else {
// 如果 key 不存在,初始化一个新的数组并设置该 key
hotMap.value.set(key, hotType);
}
};
const getNews = async (type: string) => {
const res = await request<{
data: HotType[]
}>('GET', `/api/hotList?type=${type}`)
addHotType(type, res.data)
}
watch(type, val => {
if (hotMap.value.has(val)) return
getNews(val)
})
getNews(type.value)
return {
hotMap,
type
}
})

View File

@ -1,10 +1,29 @@
import useLayoutStore from '@/layout/useLayoutStore'
import request from '@/utils/request'
import { defineStore } from 'pinia'
import { computed, ref, watch } from 'vue'
type HotType = {
desc: string
hotScore: string
index: number
picurl: string
title: string
url: string
}
export const PlatformList = new Map<string, string>([
['baidu', '百度'],
['weibo', '微博'],
['bilibili', 'B站']
] as const)
export default defineStore('video', () => {
const videoList = ref([])
const layout = useLayoutStore()
const type = ref('baidu')
const getNews = async (type: string) => {
const res = request('GET', `/api/hotList?type=${type}`)
}
watch(
() => layout.state.current,
(val) => {